3

I know this isn't valid syntax, but is there a way to accomplish something like this in servant?

type StandardAPI = "foo" :> Get '[JSON] Whatever

type CustomAPI = StandardAPI :<|> "customroute" :> Get '[JSON] Blah

in other words, composing APIs. In Spock I could do this with the monadic route construction, but I'm not sure how to do this in servant.

This way I can reuse shared routes across APIs. Another reason to use this is that there are certain types that don't work with client generators, such as Raw.

daj
  • 6,962
  • 9
  • 45
  • 79
  • 1
    This looks like valid syntax. What exactly do you want to do that `:>` doesn't do? That does compose apis. – pdexter Jun 07 '16 at 12:41

1 Answers1

8

Yes, referencing Servant documentation you can use

type CombinedAPI = "users" :> UsersAPI
          :<|> "products" :> ProductsAPI

server :: Server CombinedAPI
server = usersServer :<|> productsServer

usersServer :: Server UsersAPI
usersServer = -- implementation

productsServer :: Server ProductsAPI
productsServer = -- implementation
klappvisor
  • 1,099
  • 1
  • 10
  • 28
  • is there a way to do this without the top level "users" in the route? The problem is that code generated by servant-JS no longer works because it doesn't correspond to CombinedAPI. I can't run writeJSForAPI on my equivalent of CombinedAPI because it includes a Raw combinator which doesn't have a GenerateList instance. – daj Jun 07 '16 at 13:49
  • Sorry, cannot answer that question right now. best way to test it is to try it. I don't think `UsersAPI :<|> "products" :> ProductsAPI` is invalid thing to do – klappvisor Jun 07 '16 at 13:57
  • you're right it is valid. to do that following your example and excluding the top level piece of the route. wasn't compiling because I had the ordering mixed up in the implementation definition. – daj Jun 07 '16 at 14:05
  • Glad that everything is sorted out! – klappvisor Jun 07 '16 at 14:26