Solution to servant API type indentation problem

Posted on 2017-03-15 by Oleg Grenrus servant

This post is a literate Haskell file: so there are few imports, and {-# LANGUAGE TypedKitchenSink #-}.


How you indent your servant api types?

There seems to be an unsolvable aesthetic vs. diff-friendly problem!


Let's add a type-family!

With the help of ListApi, we can reduce the indentation problem to how we indent (type-level) lists:

The API and previously defined types are the same:


Yet to write the Server API, we still need to use :<|>. The problem is not solved properly yet. There is generic client in servant-client (PR#640), and we can use the same idea for server part too: we need one more type family and generics-sop:

This function is written in the infamous banzai mode, to convince GHC the program is well-typed. The Proxy argument is not obviously required, but the following code would be ambiguous without it. The Shape parameter in step0 is needed because GHC cannot reason backwards ServerMap xs ~ '[]xs ~ '[] (ServerMap is injective only shallowly, Server isn't injective!). We need two steps, because going directly from NP I (ServerMap ys) to Server (ListApi ys) would require to deal with two type-families at once, and GHC had Also, step1 highlights the question: should we have a type for an identity element of :<|> operation?

#An example

With the help of ListApi and listApiServer, we could define the server implementation in a neat way, IMO:

If you experiment with the code and try to change the types in ApiImpl fields, then the check "test" will catch them. It seems, that errors generated from type-checking check are way more to the point than type-errors in "classic" serve api $ endpoint1 :<|> endpoint2 :<|> ... approach.

I tend to have small wrappers around actual implementation of endpoints, (i.e. I do write apiFoo which calls businessFoo, which knows little or nothing about the web) so the ApiImpl is the only additional boilerplate.

Would this be useful? Give it a spin! Please comment either directly to me (tweet) or to servant issue.

You can run this file with

stack --resolver=nightly-2017-03-01 ghci --ghci-options='-pgmL markdown-unlit'
*Main> :l servant-server-type.lhs

fetch the source from

P.S. Someone, please fix DataKinds syntax highlighting in whatever pandoc uses!

Site proudly generated by Hakyll