Logo Questions Linux Laravel Mysql Ubuntu Git Menu
 

Haskell servant combined api implementation

I am going through the servant tutorial found here. There is a partial implementation that is left for the user to figure out what it should be.

type APIFor a i =
       Get '[JSON] [a]
  :<|> ReqBody '[JSON] a :> PostNoContent
  :<|> Capture "id" i :>
         ( Get '[JSON] a
      :<|> ReqBody '[JSON] a :> PutNoContent
      :<|> DeleteNoContent
         )

serverFor :: Handler [a]
          -> (a -> Handler NoContent)
          -> (i -> Handler a)
          -> (i -> a -> Handler NoContent)
          -> (i -> Handler NoContent)
          -> Server (APIFor a i)
serverFor = error "..." -- What should be here?

Following from the previous examples I came up with the implementation:

serverFor = listing :<|> ops

    where
        listing :: Handler [a]
        listing = error ""

        ops a i =
            creating a
            :<|> getById i
            :<|> updating i a
            :<|> deleting i

            where
                creating :: a -> Handler NoContent
                creating a = error ""

                getById :: i -> Handler a
                getById id = error ""

                updating :: i -> a -> Handler NoContent
                updating i a = error ""

                deleting :: i -> Handler NoContent
                deleting i = error ""

But am getting the error:

• Couldn't match expected type ‘Handler [a]
                                -> (a -> Handler NoContent)
                                -> (i -> Handler a)
                                -> (i -> a -> Handler NoContent)
                                -> (i -> Handler NoContent)
                                -> Server (APIFor a i)’
              with actual type ‘Handler [a0]
                                :<|> (a1
                                      -> i0
                                      -> Handler NoContent
                                         :<|> (Handler a2
                                               :<|> (Handler NoContent :<|> Handler NoContent)))’
• Possible cause: ‘(:<|>)’ is applied to too many arguments
  In the expression: listing :<|> ops

I understand what the error is saying but do not know how to implement it correctly. Is anyone able to help with what the correct implementation should be?

like image 558
HuntressMain Avatar asked Jun 07 '26 21:06

HuntressMain


1 Answers

The signature of the serverFor function says it takes handler functions and builds the Server.

serverFor list create get update delete = 
  -- combine handlers according to API type
  list :<|> create :<|> (\i -> get i :<|> update i :<|> delete i)

you can then call serverFor for your specific types.

data User = User {id :: Int}

server :: Server (APIFor User Int)
server = serverFor listing creating getById updating deleting
  where
    listing :: Handler [User]
    listing = error ""
    creating :: User -> Handler NoContent
    creating a = error ""
    getById :: Int -> Handler User
    getById id = error ""
    updating :: Int -> User -> Handler NoContent
    updating i a = error ""
    deleting :: Int -> Handler NoContent
    deleting i = error ""
like image 104
ekim boran Avatar answered Jun 10 '26 20:06

ekim boran