HuntressMain
HuntressMain

Reputation: 197

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?

Upvotes: 3

Views: 195

Answers (1)

ekim boran
ekim boran

Reputation: 1819

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 ""

Upvotes: 3

Related Questions