haskell-servant / haskell-servant/servant

Improved composability for Generic APIs

Open
#1,315 7 comments 4 reactions 0 assignees View on GitHub
Dominant language
Haskell
Stars
2k
Forks
427
Avg merge
2d 23h
Merged PRs (30d)
5

Description

There has been complaints in the past regarding the usability of APIs defined via nested generic products (see #1211 for example).

The problem with generic APIs is that one constantly needs to switch back and forth between generic and “vanilla” servant, at both term- and type-level. This is not an issue for flat APIs that correspond to a tuple of routes, but quickly becomes cumbersome when dealing with deeply nested APIs.

It occurred to me that the conversion machinery could be entirely hidden from the user, by allowing direct embedding of generic APIs via a new Servant combinator:

```haskell
data GenericAPI (routes :: * -> *)
```

For which suitable instances could be defined, directly declaring clients and servers for `GenericApi MyRoutes` as _records_:

```haskell
instance ( … ) => HasServer (GenericApi routes) context where
type ServerT (GenericApi routes) m = routes (AsServerT m)

instance ( … ) => HasClient m (GenericApi routes) where
type Client m (GenericApi routes) = routes (AsClientT m)

```

I have taken a stab at it in [this gist](https://gist.github.com/gdeest/27d41541839bae947997bec52c519b51). Please disregard the quality of the code, this has been thrown together in a hurry :)

There is some ugly machinery there, but it works fine with servers. I haven't been able to write the `hoistClientMonad` function for clients though (it looks like we would need additional constraints on the monad type constructors for this to work), but clients in vanilla `ClientM` should work.

Do you think this idea is worth pursuing ? Has this been tried before, or this somehow in violation with the Servant philosophy ?

Contributor guide

Open the contributing guide

Assessment

This issue has not been assessed yet.

Get new issues in your inbox

A short digest of beginner-friendly GitHub issues.