

Show HN: Servant – A Haskell web framework with type-level API DSL - jkarni
http://haskell-servant.github.io/

======
jkarni
We came up with a way of reifying specifications of web APIs at the type
level, and built a web framework around it. The basic idea was, I believe,
first developed by Ralf Lämmel and Klaus Ostermann [0], as a Haskell solution
to the expression problem, but I think it's the first large-scale application
of these ideas.

Checking for correctness and deriving functionality from that comes pretty
naturally after that, so it's easy to reduce boilerplate (e.g., generate
client libraries and documentation automatically) and make static guarantees
(e.g., that a link exists within an API, and won't 404).

[0] [http://www.informatik.uni-
marburg.de/~kos/papers/gpce06.pdf](http://www.informatik.uni-
marburg.de/~kos/papers/gpce06.pdf)

------
PhineasRex
Having the type-system statically verify that your API is correct and that
your usage of it is correct, but oof, that syntax is quite hard to read. I
wonder if you could use Template Haskell to generate that from an easier-to-
read routes file similar to Yesod.

~~~
jkarni
We had QQ originally, but removed it because it wasn't extensible (you can
define new expressions in the type-level DSL, but you couldn't add them to the
QQ). We've figured out how to do that now, and there's an issue someone opened
asking for it back ([https://github.com/haskell-
servant/servant/issues/55](https://github.com/haskell-
servant/servant/issues/55)), so it'll probably soon return.

You do get kind of used to it, though, for what it's worth. And you can always
break things up. E.g.:

    
    
        type MyAPI = "users" :> Get '[JSON] User
                  :<|> "users" :> ReqBody '[JSON] User :> Post '[] ()
    

Can generally be rewritten as:

    
    
        type GetUser = Get '[JSON] User
        type PostUer = ReqBody '[JSON] User :> Post '[] ()
        type MyAPI = "user" :> (GetUser :<|> PostUser)
    

etc.

