Exporters From Japan
Wholesale exporters from Japan   Company Established 1983
CARVIEW
Select Language

This post is an attempt at explaining servant’s design as an embedded domain specific language, and particularly why it had to be a type-level domain specific language, given our requirements. Along the way, we will discuss approaches for designing extensible EDSLs in Haskell and see why other simpler approaches just can’t meet the said requirements.

It all started with a problem

Back in 2014, Sönke Hahn, Julian Arni and myself were working together in “the Haskell team” at Zalora on all sorts of projects. Many of them involved serving web applications, querying external APIs or our own services from Haskell, PHP, JS and probably a few other languages. At the time, we were using a few of the well established “web frameworks”, among which scotty, whenever we had to offer some service over HTTP.

However, writing all those functions for hitting our own webservices was a lot of manual, error-prone, tedious work. The bigger web applications got, the more tedious it became. And it had to be done once per language in which we wanted to hit the application. This could not continue.

For reference, this is what a simple scotty application looks like:

How could we somewhat automate the creation of one client function per endpoint of the web application? In an ideal world, we would just show this application to some program or library and it would collect all the data it needs about the overall structure of the application from the code itself, in order to produce 2 client functions:

which would do all the hard work of preparing an HTTP request for us, even taking care of JSON encoding and decoding for us. But… the entire structure of the application is just hidden in the do block and we just cannot programmatically access it.

So… this is not realistically doable. We clearly need to change (a little bit? a lot?) the way we write our applications, making sure we get a description of the web’s application structure (the endpoints, the part of the request they use or depend on, what they return) that we could then hand over to something, which would get us our client functions.

We will now try implementating such a web application description DSL in the most straightforward way possible.

Note: We could define a DSL with an interpreter that spits out Haskell code for us (through Template Haskell or another mechanism). The result would be typed, but the process would not be. The translation from the DSL to the result would be untyped code, therefore easy to get wrong. As Haskell programmers, we prefer static type checking where possible. This therefore excludes Template Haskell and other code generation mechanisms.

A first, non-modular attempt

We want to produce client functions that look like the ones above, that prepare and send HTTP requests for us by taking some pieces of data given as arguments to those functions and encoding then storing them in the right places of the request (request path for URL captures, request body, headers, etc). Let’s perhaps start simple with a data type for describing an endpoint that can be served under some path (which can contain static string fragments and captures), for a given http method, ignoring everything else for now.

It could look like this:

and, if we want it to look a little more “servant-y”, we can define:

Unlike servant though, as you can see with the type of getHello and getHelloNew, our descriptions are good old Haskell values, both of the Endpoint type.

Given those few definitions, how could we go about, say, generating links to endpoints? Well, here is a straightforward attempt.

But… what should we put in place of those ???, if anything?

Well, we definitely want to add some path component, to fill the Capture slot. However, by definition, a captured path fragment is not fixed, it is allowed to vary. In other words, Capture :> Verb Post matches both POST /x and POST /y. We cannot just pick one value and hope that it is the one the user wanted. We need to take it as an argument. But what about Capture :> Capture :> Verb Post? We would need our linkTo function to take 2 arguments for that case. And zero additional argument for Static "hello" :> Verb Post. This is quite problematic.

Indeed, we would like the type of linkTo to be Endpoint -> Link, Endpoint -> String -> Link, Endpoint -> String -> String -> Link and so on depending on what the Endpoint argument is. In other words, we want the return type of linkTo (when really seen as a function of one argument, which it is anyway) to depend on the value of type Endpoint it gets as input. That is, we want a type that depends on a value, i.e dependent types.

The alternative would be:

This solution is very unsatisfactory, first and foremost because it is possible for it to error out if we don’t supply the right number of captures. However, it will also silently let us pass too many capture values without telling us that some of them are not used. Such a function should be total, we really don’t want an implementation that can let us down if we’re not very careful.

Fortunately, GADTs can help here. We could turn Endpoint into a GADT that tracks captures and then use some type-level computations to get the type of the link-making function from our list of captures, as well as define the link making function through typeclass instances that would go through the captures and add an argument for each of them. Request bodies, query parameters, headers? We could probably track them too, in a similar way. Or we could unify it all by basically building up and tracking actual servant API types through a GADT version of Endpoint’s type argument, and do some of what servant does at the type-level, with everything else at the value-level.

However, all those approaches have a big problem. Once you’ve made a decision, it is set in stone, in a way. Indeed, in all these approaches, if you want to extend your web app description language, you need to add a new constructor to your Endpoint type. You then need to handle this new constructor in all the functions that pattern match on Endpoint constructors since they’ve instantly become partial. Not to mention that just the act of adding a constructor requires rebuilding the entire library. You cannot explore two different directions simultaneously without breaking code, you cannot add new constructs you hadn’t thought of without touching the library, e.g just locally in a project of yours. Extensibility and modularity were central requirements as we had been bitten by the lack of them in libraries that we were using at the time.

Note that a GADT-based approach would work well (in addition to being more approachable) for very stable domains, and is not considered here because of the kind of flexibility we are asking for.

So… how do people build extensible/modular DSLs in Haskell? The next section talks about the general problem behind this and a solution that I read about that gets us halfway to servant.

The Expression Problem

To quote Phil Wadler: “the expression problem is a new name for an old problem. The goal is to define a datatype by cases, where one can add new cases to the datatype and new functions over the datatype, without recompiling existing code, and while retaining static type safety (e.g., no casts)”.

In Haskell, the standard approach to representing some domain is to define an algebraic data type for it. For a simple type of expressions with additions and integers, we usually do:

and proceed to write what we call “interpreters”, which in this case are just functions that take expressions as input and do something interesting with them.

So, given an expression type, we can easily “add new functions over the data type”, to reuse Phil’s wording. We just write a new function. However, when the time comes to “add new cases to the data type”, this approach becomes painful. A “new case” here means a new constructor for our Expr data type. Let’s say we want to support multiplications too:

Now, we have to modify every single function that patterns matches on an Expr to handle the Mul constructor, including our eval and prettyPrint “interpreters”. For any non-trivial domain, this becomes very painful, very quickly. Fine, so what other options are there?

Ralf Lämmel’s slides on the topic have been of a great help for me, back when we were looking for a solution suitable to our needs. With Oleg Kiselyov, they show how we can reasonably easily (that is, in Haskell 98) achieve full extensibility in both directions (constructors and interpretations) in Haskell. It boils down to:

  • Turn what would be a constructor into its own little data type.
  • Turn what would be a simple function that operates on the data type into a typeclass with a method.
  • Write instances of those typeclasses for the data types representing the DSL’s constructs.

This effectively means that we won’t have a single type to represent all the valid “endpoint descriptions”. Instead, with this approach, we will be able to process any “reasonable” combination of “endpoint components”. The Expr typeclass below is exactly what lets us say what is a valid endpoint description and what isn’t. Using their approach for our expressions would look like this:

Every constructor that we had in our previous Expr data type is now turned into its own little type, and every interpretation becomes a type class that all those little types are then free to provide an instance for. In fact, we do not necessarily have to supply an instance of each interpretation for all of our constructs. If we try to interpret an expression that uses a construct not supported by this interpretation, we get a type error! This is much better than calling error in some corner cases that should in theory not be reached… In theory. Right.

Anyway, if we now want to add support for multiplications, we can do:

We didn’t have to change any existing function, that’s great! Let’s apply this approach to a very simplified web application description “language” that we could make out of tiny building blocks (static path fragments, captures, etc).

A first modular attempt

Adapting the approach from the previous section to our domain, we can give a shot at decomposing the kind of information we want to represent into a few different “constructs” (i.e data types).

OK, why not. Let’s now try to write an interpretation for generating links to endpoints like the one above. This is a lot simpler and self-contained than investigating client generation or server-side routing, while retaining many of the difficulties. The main one is that depending on what we find in the description of the endpoint, we need the type of the link-generating function to change: indeed, if we encounter Captures, then the user has to supply values for them. We will let the user do that through one additional argument per Capture we encounter.

Let’s start with something really simple.

We should be appending something in place of those ??? there. But since Capture represents variable path fragments (like :userid in /user/:userid, in many web frameworks), we do not want to pick a fixed string, we would like for this string to be supplied by the caller of link, as stated above. Let’s introduce a slightly fancier HasLink class to make it seemingly “variadic”.

Looks good. Except that this does not typecheck. The problem is with the Capture :> api and Static :> api instances. While we know that the link function will eventually return a Link, once given arguments for all the Captures, we don’t know whether there is another Capture later in api. If there is, then link api would have type e.g String -> Link, and we cannot cons a String on top of… a function.

We have to be a little smarter and accumulate the path components as we go without building up the final list directly. We will be accumulating the path components in reverse order, to make the accumulation efficient, and reverse the whole list at the end to give the final Link (= [String]) value.

We can finally generate links with the new approach:

This looks promising. Let’s now try to introduce some more types here, by allowing captures to not be specified just as simple strings, but any Showable type (this is terrible, but simple enough for this post). We need to modify Capture to track that Showable type we will use to specify the value of that path fragment.

We unfortunately cannot just “track” some type by storing it in a field (which is different from storing a value of that type). Instead we make Capture a clone of Proxy (from Data.Proxy) and just carry around a phantom type parameter. This is a little inconvenient as we will have to type annotate all Captures (or use the TypeApplications language extension), but let’s roll with this approach for now.

Let’s now see an endpoint description using this variant of Capture.

OK, interesting, why not. It does look a little bit ugly. It would look even uglier if we included the response type in Verb, turning it into data Verb a = Verb Method which would require the same kind of type annotations. And the same problem would manifest itself if we were to add all the similar types from servant (ReqBody, QueryParam, Header, etc). This is quite disappointing.

Unrelatedly, have you noticed that I have not given the type of any of our endpoint descriptions so far? This is on purpose, because those types are a little bit fancy. Fortunately, they should look familiar:

That’s right, not only do the descriptions (which are good old haskell values) look like servant’s API types, but their types too! We can see that we are only “hiding” the strings (in static path fragments) and the HTTP method (in verbs) from the type-level.

Most of the other bits of information we would want to see in API descriptions will also have to be reflected at the type-level. When we consider content types for example, we have no choice but to keep track of them at the type level too, even with this design. Because we need to make sure suitable encoding/decoding instances are available for the types that will be represented with those MIME types, and this cannot be done when discovering "application/json" in a list somewhere, at runtime.

All in all, there is no value in keeping anything at the value level at this point. And we are already traversing a bunch of types mixed together with funny symbols and computing the type of a link making function as we go, as evidenced by the HasLink instances from above, so we’ve already got one foot in type-level land.

An important tradeoff that we are making here is that while putting more information at the type-level indeed makes things more complex, it does however give a chance to our descriptions to influence more things, including other types. This is noticeable in the last HasLink instance we wrote, where making Capture track the type the url fragment is going to be decoded to allowed us to directly make the link-making function take a value of that type, instead of a string. This is strictly more powerful and will allow us to work in a very strongly typed world and where the typechecker “writes” a whole lot of code for us.

Let’s bite the bullet and finally take a quick look at what servant’s type-level approach looks like.

Servant’s approach (simplified)

First, let me emphasize that any of the designs we have considered so far are interesting on their own and are fruitful in different ways. They were not quite good enough to meet our requirements which were, again, dictated by the projects and needs we had at work. This whole project started because we were sick of getting things wrong when manually constructing (client) or deconstructing (server) HTTP requests and so on.

Now, let’s write our type-level DSL. If you want a longer version of just this section, with more explanations, you may want to read Implementing a minimal version of servant.

As you can see, there isn’t a single constructor in sight, all the types (but Method) are empty. And now, we proceed with the HasLink class. Since we don’t have any value to give to the link method, given that the description is now a type, we will use data Proxy a = Proxy to act as an intermediate between the value level, where the calls to link will happen, and the type level, where the descriptions live and drive the link interpretation through our typeclass instances.

It is not all that different from the code in the previous section. We can use it all as follows:

And that’s it! The key ingredients to servant’s design are all here. If you want to read more about actually implementing server/client interpretations for the DSL, the Going further section has got you covered with a few relevant links.

Conclusion

I hope this little tour of some of the designs we explored on our way to writing servant was useful and informative, whether from a Haskell EDSL writer perspective or for any Haskeller who has ever wondered about why the descriptions live at the type-level. The real servant libraries of course have a much richer vocabulary for describing endpoints and entire APIs, and offer many interpretations in addition to the type-safe links. But the core ideas behind the design and implementation are the same ones we progressively arrived at in this post.

Going further

  • Servant, Type Families, and Type-level Everything - A look at advanced GHC features used in Servant

    I suspect this is a rather useful resource for Haskellers who haven’t yet encountered type-level programming in (GHC) Haskell.

  • Implementing a minimal version of servant

    A more approchable and more narrowly focused alternative to the servant paper, which consists in implementing a very simplified version of servant, using however the same “API type” based approach for the EDSL as the real servant.

  • the servant paper, published at the Workshop on Generic Programming, 2015.

  • Software extensions and Integration with Type Classes

    by Ralf Lämmel and Klaus Ostermann talks in greater depth than the slides about the highly modular approach to embedded domain specific languages in Haskell that we’ve seen above, and uses it on several examples.

  • serv and solga are smaller, younger and (I think) humbler relatives of servant which make slightly different choices for the DSL.

    Somewhat relatedly, there is servant-0.1, which wasn’t anything like the current approach with its API types. The link leads to its README, with an example and some explanations about the approach, for the curious reader.

]]> Thu, 12 Jul 2018 00:00:00 UT https://haskell-servant.github.io/posts/2018-07-12-servant-dsl-typelevel.html servant developers servant 0.14.1 released https://haskell-servant.github.io/posts/2018-07-05-servant-0.14.1-released.html We’re happy to announce the minor release of servant-0.14.1.

]]>
Thu, 05 Jul 2018 00:00:00 UT https://haskell-servant.github.io/posts/2018-07-05-servant-0.14.1-released.html servant developers
servant 0.14 released https://haskell-servant.github.io/posts/2018-06-19-servant-0.14-released.html

Table of contents

Introduction

We’re happy to announce the release of servant-0.14. This is relatively small release, still containing some new features and breaking changes.

Significant changes

Other changes

]]> Tue, 19 Jun 2018 00:00:00 UT https://haskell-servant.github.io/posts/2018-06-19-servant-0.14-released.html servant developers Passing a DB connection to handlers in Servant https://haskell-servant.github.io/posts/2017-03-03-servant-and-db.html This post is originally published in https://oleg.fi/gists/posts/2017-03-03-servant-and-db.html. This version is updated to use hoistServer.

This write-up is motivated by discussion in servant/#704 issue. I try to summarize the main points.

As this is a literate haskell file, we’ll need to do a small prelude dance:

The problem

The issue started as instance XY-problem:

  • Y: Docs explaining how to actually create a full combinator (ex. one to create/store a DB connection)
  • X: How to pass a db connection to the handlers.

I won’t answer to the Y, how to write combinators is different topic (have to write about that later). Let’s see how to deal with X, by implementing a small Cat CR(UD) API:

Now we’ll need to implement the api, we’ll write a basic Haskell functions, which we would write anyway, we could reuse them in a console application, for example.

And the problem is that if we try to do

-- THIS DOESN'T WORK
app :: Application
app = serve api $ createCat :<|> readCat

it will fail with a type-error message from GHC. Obviously, GHC cannot conjure Connection for us. We need to pass it in somehow.

Partial application

Partial application is a simple tool. We can partially apply the implementation to fit into type required by serve. We’ll make a situation a bit more interesting by using a connection pool:

As you can see we’d need to wrap every handler in withResource1. It’s not very elegant, but it works. And is very simple to understand.

hoistServer

servant offers the hoistServer helper function. which let’s you to remove this kind of boilerplate. We’ll rewrite our handlers in MTL-style, with a MonadDB type class. For the sake of example let’s also add a MonadLog from log-base to the first endpoint.

Looks good, but how we’ll pass a connection (and a logger)? The answer is obvious, when you know it: we’ll need to use a concrete monad implementation, for example:

And now hoistServer will do the magic:

The nt (for natural transformation) tells how to transform the concrete monad H into servant’s Handler. The hoistServer machinery walks through ServerT H value and applies that transformation, resulting into ServerT Handler value. If api has HasServer instance, you can hoistServer it.

The hoistServer is most useful when you have polymorphic handlers defined with mtl-like monad type-classes, so you can instantiate them all with the same concrete monad at then end. Note: that if we had concrete LogT Handler in some handler, and ReaderT (Pool Connection) Handler in some other one, hoistServer won’t help!

So to conclude:

  • start with partial application to pass arguments into handlers
  • later you may transfer to use fancier hoistServer.

Alp Mestanogullari summarised it well: gradually reach for fancier things as your needs grow, never when it’s not required.

]]>
Fri, 03 Mar 2017 00:00:00 UT https://haskell-servant.github.io/posts/2017-03-03-servant-and-db.html servant developers
servant 0.5 released https://haskell-servant.github.io/posts/2016-03-19-servant-0.5-release.html

Table of contents

Introduction

We’re happy to announce the release of servant-0.5. Quite a lot of exciting changes have happened since the last major release. A lot of things happened under the hood, but there’s also a number of changes on the surface. This will force servant users that want to upgrade to perform some changes to their code. Therefore the following section contains an upgrade guide. We hope, upgrading will go smoothly. At least when you didn’t write your own combinators it should be fairly straightforward.

The second section of this blog post contains a description of the major new features in servant-0.5.

Upgrading

servant-server

  • Instead of EitherT (from either) we now use ExceptT (from mtl), which behaves the same, but doesn’t add a dependency. Your handler’s types have to change from e.g. EitherT ServantErr IO MyType to ExceptT ServantErr IO MyType. Throwing an error used to work with e.g. left myError and that now has to be switched to throwE myError. Both ExceptT and throwE reside in Control.Monad.Trans.Except.

  • Post now returns 200. Replace Post with PostCreated if you want to stick to the old behaviour, which was returning a 201.

  • Methods returning () do not automatically return 204 anymore. Use GetNoContent (and PostNoContent, etc.) in conjunction with the NoContent type instead:

  • MatrixParam has been removed.

  • The content-type list now is invariably used to determine whether to respond – that is, even when you’re returning NoContent you need to specify matching content-types.

servant-client

  • client now takes a Manager parameter. (See Manager.)

  • MatrixParam has been removed.

servant-docs

  • ToSample now only takes one type parameter.

  • MatrixParam has been removed.

If you have your own combinators

Then the story is more complicated. The HasServer class changed quite drastically:

Read below for more information.

Major Changes

Trie-based routing

Previously routing was O(n) in the number of routes, as we matched them sequentially (and indeed, bodies would sometimes be deserialized more than once). Andres Löh improved this by transforming the routing into a trie.

Proper error handling

One of the biggest embarassements for servant was the fact that in certain circumstances, the HTTP error returned was not what one would expect. For example, if a request had both the wrong method and the wrong body, the error returned would be 400 (Bad Request) rather 405 (Method Not Allowed). This was because we matched against parts of your API in the order they appeared in your API type. Andres Löh came up with an elegant solution to this problem, creating a datatype that allows checks (and their side-effects) to be delayed.

This allows for a fine-grained control over when side-effects and general HTTP logic is run. Currently there are five ‘slots’ for effects:

Which are run in the order in which they appear in the code. Helper functions can be used to add more effects. In practice, this means that if you are writing a combinator for authentication, for example, you can simply use addAuthCheck to schedule your action. It will only be run if the captures and methods match, but before the body is looked at.

These five slots do not exhaust the steps of handling an HTTP request. But rather than straight away implement a very large datatype for the entire HTTP decision diagram, we decided to implement what was needed for the official servant combinators. We now want to gather some experience to see, if something’s missing. So if you feel like another slot is needed, open an issue!

Context machinery

We had an issue that kept annoying us. Consider a HasServer instance for a combinator that provides a User by looking up the cookie in a database. You have to be able to somehow pass the lookup function – or at least a connection to a database – into that instance. But they must be passed in at run-time, and for fairly involved reasons there was no good way of doing so.

We added a new parameter to route that is an HList with configuration data not unlike Spock’s Context. If you are not writing HasServer instances, Context requires no changes to your code for upgrading. If you are, note that the HasServer type class has an extra type parameter.

This change should enable a variety of new combinators that were difficult or impossible previously. Note that Context is (for now at least) meant only for the configuration of combinator instances, not for the configuration of handlers (use enter for the latter).

http-api-data

The type classes FromText and ToText have been renamed, revamped, and relocated. They are now called FromHttpApiData and ToHttpApiData respectively, and exist in the new package http-api-data. This was work by Nickolay Kudasov, and includes a variety of other improvements. Most noticeably, rather than having a single [de/]serialization method, there are now ones for each of the cases for which we need the [de/]serialization. (This was based on an idea from Greg Weber.):

As an added bonus, the Template Haskell for persistent generates these automatically, making using persistent with servant a lot easier.

The haddocks for the package have more information.

Simplify ToSample

ToSample now takes only one parameter. It was an annoying mistake that it ever took two, which Nickolay Kudasov fixed. Additionally, instead of having two methods (toSample and toSamples) defined in terms of one another, we now have a single one (toSamples).

Nickolay also made a Generic default method for this class, so that now you could simply have:

Unifying method combinators

Previously each of ‘Get’, ‘Put’, ‘Post’, etc. were entirely separate datatypes. This also meant each interpretation needed to included instances for all of them. The 0.5 release makes them instead type-synonyms, e.g.:

This makes it easy to change the status code of a success response. To further facilitate that, we now provide a variety of other type synonyms for responses other than 200, for example PostCreated for 201.

Non-memoized request body

Prior to Andres Löh’s trie-based routing improvements, we had to keep the request body in memory for more-or-less the duration of the request-response cycle. This was of course far from ideal, but necessary given that we could not tell whether the request might be re-routed to a different endpoint. After the changes, we can now remove it. Note however that certain idioms, such as

no longer make sense – a request body that cannot be decoded as an Int will be rejected with a 400, and the second endpoint will not be tried. This accords with the behaviour of more traditional frameworks and, as Edsko de Vries showed in a blog post, no loss of expressivity is entailed by the change.

We expect this to enable streaming combinators.

Remove matrix params

Matrix params were interacting poorly with the rest of servant, because they necessitate special behaviour. We decided to remove them. If you were relying on them and would like to see them back, please let us know.

Switch from EitherT to ExceptT

Along with the rest of the world, we’ve moved to ExceptT, which is in mtl. Updating should consist of just replacing all occurrences of EitherT with ExceptT and all occurrences of left with throwE.

Manager and BaseUrl as an argument

Previously the http-client Manager – which is used to issue http requests – was created (with unsafePerformIO) by the servant-client library itself. This meant that it was impossible to configure the Manager. Now the Manager is passed in as an argument to client:

We’re not entirely happy with this solution, since sometimes you want the endpoint1 functions to take these two arguments instead (for example, if you would like to distribute client functions as a library). But it is certainly an improvement.

NoContent and status codes

Previously we were much too smart about HTTP status codes. In particular, when the type of the response was (), we would return 204 (No Content). This was sometimes convenient, but generally more trouble than it was worth – some people wanted 200 codes anyhow, some people pointed out that 205 (Reset Content) was also often a sensible response, and moreover, () was too generally-used a type to convey the appropriate semantics. We now have a dedicated NoContent type for that, and the status code is up to you to decide (by default it will continue to be 200).

NOTE: additionally, and for many of the same reasons, Post now returns an HTTP 200 on success (rather than 201). Use PostCreated if you would like the old behaviour.

servant-js

The javascript codegen story has been considerably improved. Not only is there jquery-based codegen, but also Angular, Axios and vanilla (xhr-based) codegen. freezeboy wrote a separate post going into more details about how all of it works – stay tuned for it.

Furthermore, we have extracted common functionality for code-generation into servant-foreign. During this change, we have switched from String to the text-package. So if you were using servant-jquery before and are now switching to servant-js, take into account that we do not use the String datatype anymore.

servant-foreign

There has been a proliferation of code-generation libraries for servant. With this in mind, Denis Redozubov wrote servant-foreign is a library purposed to address the common code-generation needs. It derives the term-level endpoints descriptions from the servant typelevel API DSL. Once you have this, it’s easy to implement code-generation for any target language. In the nutshell it allows you to generate http api clients for servant servers and incorporate that into your build/CI process. servant-js and some other libraries use servant-foreign under the hood to achieve this.

Auth

One of the most drawn out discussions and PRs in servant has been Auth. Aaron Levin was patient enough to work through several ideas as all of us explored the design space. We currently have two auth combinators: a BasicAuth combinator, and a still somewhat experimental but more general AuthProtect combinator.

Basic Auth

(NOTE: Basic Auth sends text in the clear, so only use this over HTTPS!)

An API protected by Basic Auth in servant looks like this:

Where User is an application-specific datatype that your handlers will receive as an argument in case authentication succeeds.

servant needs to know how to generate a User from a username and password string. For that, we use the new Context mechanism.

Documentation

Sönke Hahn has done a lot of work improving our tutorial and documentation. We have moved to Read the Docs, which should make it easy to provide documentation for multiple versions of servant. We have also moved towards literate Haskell, which has already improved the quality of the documentation.

Release Management

servant-0.5 was a long time in the making. We initially hoped to cut a release last summer. In the future we hope that we can move to a much more aggressive release managament. So we hope servant-0.6 is coming soon, with a lot less changes.

Conclusion

We hope you enjoy the new release. It was certainly lots of fun to work on servant-0.5. We’d like to say thanks to all the people that helped, big or small. Happy hacking.

]]> Sat, 19 Mar 2016 00:00:00 UT https://haskell-servant.github.io/posts/2016-03-19-servant-0.5-release.html servant developers Announcing servant-swagger and swagger2 https://haskell-servant.github.io/posts/2016-02-06-servant-swagger.html Servant is not the first project to provide a unified way of documenting APIs. There is API Blueprint, RAML, Apiary, and finally swagger. While these Web API description languages are not also web frameworks , they are generally very mature, and have some amazing tooling. For example, take a look at what swagger-ui, a client-side HTML, CSS, and JS bundle, does with your swagger API description here.

As you can see, it’s a very convenient and approachable way of exploring your API. In addition to an easily-navigable structure, you can build up requests and send them to your server, and see its responses.

But it doesn’t end there. If you have a swagger specification of your API, you can also take advantage of the large variety of languages for which you can generate a client library automatically. You don’t even need to build the Java code - you can just use the “Generate Client” button in the beautiful swagger editor.

There are a wide array of other tools that support swagger. Obviously, having access to them would be a great boon. The problem so far has been that writing and maintaining a swagger specification, that you can be sure matches your service, is hard work.

swagger2 and servant-swagger

Thankfully David Johnson and Nickolay Kudasov have written two Haskell libraries, swagger2 and servant-swagger, that automate nearly all of that process for servant APIs. They use the mechanism that guides most of the servant ecosystem — interpreters for the type-level DSL for APIs that is servant — to generate a swagger spec for that API.

Let’s see how it is used; as an example, we’re going to take the Gists part of the GitHub API v3. For the purpose of this post we will ignore authentication and consider only GET requests which do not require one. Furthermore, we’ll use simplified representation for the responses (i.e. we are also ignoring some fields of the response objects).

First the imports and pragmas (this is a literate haskell file):

The API:

Data types:

FromJSON instances:

So far this is what you would usually have when working with servant. Now to generate Swagger specification we need to define schemas for our types. This is done with ToParamSchema and ToSchema instances:

These will give us a generically-derived Swagger schema (which is sort of a deterministic version of JSON Schema).

Part of the swagger2 package, Schema and ParamSchema can be quite useful in their own right if you want to e.g. respond with a schema in case of bad request bodies, or OPTIONS requests.

The next step will traverse the GitHubGistAPI, gathering information about it and swagger2 schemas to generate a Swagger value:

Now we can generate the swagger documentation:

You can attach more information to your Swagger doc quite easily, using the lenses provided by swagger2:

Which results in this.

There’s a lot more you can do with both servant-swagger and swagger2 — write manual ToSchema instances for more detailed information, conveniently add tags or change responses of parts of your API, use convenient lenses to modify any part of your schema, generate automatic tests, etc.

Check out the servant-swagger and swagger2 docs for more.

These two new packages vastly expand the landscape of tools within easy reach of application developers using servant. Time to explore that landscape!

On a related note, Masahiro Yamauchi has recently added Servant codegen for Swagger. So not only can you generate a swagger description for your servant server, but you can also generate the servant description from a swagger one too!

]]>
Sat, 06 Feb 2016 00:00:00 UT https://haskell-servant.github.io/posts/2016-02-06-servant-swagger.html servant developers
Content Type Bliss https://haskell-servant.github.io/posts/2015-08-05-content-types.html Recently I came across Timo von Holtz’s servant-JuicyPixels package. It describes servant-compatible content-types for JuicyPixel’s DynamicImage data type, and clocks under 100 airy lines.

Timo and I realized there is a pretty neat demonstration of the advantage of abstracting away content-type serialization and deserialization: the world’s most concise image-conversion web service. Essentially the same application is available as the image conversion example in Timo’s package.

(If you want to know more about how content-types work in servant, the content-type section of the tutorial has more information.)

The Application

Our goal is to provide a service that converts images between formats based on the Content-Type and Accept headers of the request:

$ curl localhost:8001 -H "Content-Type: image/png"  \
                      -H "Accept: image/jpeg"  \
                      --data-binary "@haskell-logo.png" \
                      > haskell-logo.jpeg

To get there, we need to do a couple of things. We need to of course run the application:

And describe the API:

As you can see, we state that we accept and can return a variety of image formats.

The application is then:

And for the clincher, the handler:

And that’s it!

Conclusion

This is just the limit of the relative gain of abstracting content-types - there is nothing to the application besides them!

Essentially the same idea could of course be applied to other areas. Document conversion with Pandoc, video and audio formats, etc.

]]>
Wed, 05 Aug 2015 00:00:00 UT https://haskell-servant.github.io/posts/2015-08-05-content-types.html servant developers
Pulling a mock server for your APIs out of thin air https://haskell-servant.github.io/posts/2015-07-24-pulling-mock-servers-out-of-thin-air.html

Table of contents

Summary

A couple of days ago, marcushg mentioned on the #servant IRC channel that one could probably easily use the information available from API types to “derive” a mock implementation of your request handlers that just generates random values of whatever the return type of the handlers are. Julian and I discussed this a bit today and I just went ahead and wrote down our thoughts in a new branch. The result will be explained in this post, but in short, it lets us take a type describing a web API, such as:

and generate request handlers that just respond with random values of the appropriate type, User in our case. In servant/wai terms, this means we get a mock function with the type:

i.e., “given an API type, please generate a mock server for such an API”. This effectively means “please pull a mock server out of thin air for me”.

Out of thin air, really? Not exactly. But let’s start by clearly stating the problem.

The Problem

servant lets you describe web applications with a Haskell type using the combinators from servant’s type-level EDSL. Such a type would be:

where User could be defined as:

The goal would be to “automagically” derive a request handler of the right type that we could use as a placeholder until we properly implement a handler that talks to the database and responds with “the real data”.

For anyone not familiar with servant already, you just need to know that it means we need to somehow automatically implement a computation with the type:

possibly by constraining the user to provide an instance for some random generation class.

The Plan

Just like servant-server, servant-client and others, we need a class whose instances will define the way we interpret each combinator, in a way very specific to this task: we will produce what servant-server takes as input, i.e., request handlers! This all means we are basically looking at a class like:

where Server api just computes the types of the all the request handlers of an API type. In our case, Server api is computed as follows:

So we have to implement at least support for static string fragments in the path and the Get combinator (i.e handlers for HTTP GET requests).

HasMock instances

Let’s start with the one for static path fragments, it’s the simplest one: we ignore the string bit and move on to what comes after.

Don’t be scared by KnownSymbol, it basically just means “path is a type-level string”, that is, a string that appears in a type.

Next comes the one for Get. This one is trickier: this is the combinator that says what type the handler returns. The returned value then gets encoded into JSON, HTML, CSV or any format of your choice. In our case, the handler returns a User and can only encode it in the JSON format.

Now the heart of the matter really is: we know we need to return an User and our EitherT ServantErr IO monad mentions IO, couldn’t we randomly generate an User? Yes, we can! For the purpose of a mock server, we will simply use QuickCheck’s Arbitrary class, which represents types for which we can generate random values, given a random number generator.

The Gen type provides instances for the Functor, Applicative and Monad classes and Arbitrary comes with instances for many of the types in base.

This essentially means writing an Arbitrary instance for User is as simple as:

If you have multiple fields, you can use the usual combo of <$> (i.e., fmap) and <*> (comes with Applicative).

Once you have an Arbitrary instance, in order to generate a random value using your instance, you have to call a function called… generate!

Putting the two together, we get:

All we need to do is just “lift” that up into our EitherT ServantErr IO monad, which is exactly what Control.Monad.IO.Class.liftIO is about in the transformers package.

In order to automatically “fill” request handlers with this expression we just need to write the HasMock instance for Get, shown below.

The AllCTRender constraint just says “we know how to encode values of type a in the formats listed in the Get combinator”.

And that’s it! You can now actually use all of this to put together a mock server for our little API.

Using mock

All we need to do to run the mock server is call servant-server’s serve function. It is illustrated below, along with all of the code you’d have to write if you were to use this mock-generation feature (aside from language pragmas and imports).

Our little program in action:

This is really all you have to do to put together a mock server for an API type. You can find the complete code for this in the work-in-progress servant-mock package on github. The example can be found under example/main.hs there.

There are many more HasMock instances than the ones I have shown here of course – there’s one for all the combinators provided by the servant package! So you can take any API type out there and just create a mock server for it, as long as you provide Arbitrary instances for your data types. Nothing too interesting though, but feel free to take a look at src/Servant/Mock.hs in the repository if you want to read the other instances.

I hope this makes clear how simple writing your own servant interpretation can be, and encourages you to try your hand at it!

Other news

  • I mentioned in a previous post that we had submitted a paper for the Workshop on Generic Programming, co-located with ICFP’15, in Vancouver this year. Well, the paper has been accepted!
  • Therefore, Julian Arni and/or Andres Löh will be giving a talk about servant there.
  • In addition to this, Julian Arni recently gave a talk about servant at Curry-On!. The video will be uploaded on their Youtube channel in the upcoming days.
  • I have submitted a very hands-on servant talk proposal for the Haskell eXchange 2015 in London, and it has been accepted! See you there, folks.
]]> Fri, 24 Jul 2015 00:00:00 UT https://haskell-servant.github.io/posts/2015-07-24-pulling-mock-servers-out-of-thin-air.html servant developers servant paper submitted to WGP 2015 https://haskell-servant.github.io/posts/2015-05-25-servant-paper-wgp-2015.html Sönke Hahn, Julian Arni, Andres Löh and myself have submitted a paper about servant to the 11th ACM SIGPLAN Workshop on Generic Programming. Here’s the abstract.

We describe the design and motivation for Servant, an extensible, type-level DSL for describing Web APIs. Servant APIs are Haskell types. An API type can be interpreted in several different ways: as a server that processes requests, interprets them and dispatches them to appropriate handlers; as a client that can correctly query the endpoints of the API; as systematic documentation for the API; and more. Servant is fully extensible: the API language can be augmented with new constructs, and new interpretations can be defined. The key Haskell features making all this possible are data kinds, (open) type families and (open) type classes. The techniques we use are reminiscent of general-purpose generic programming. However, where most generic programming libraries are interested in automatically deriving programs for a large class of datatypes from many different domains, we are only interested in a small class of datatypes that is used in the DSL for describing APIs.

The full draft is available here.

]]>
Mon, 25 May 2015 00:00:00 UT https://haskell-servant.github.io/posts/2015-05-25-servant-paper-wgp-2015.html servant developers
servant 0.4 released https://haskell-servant.github.io/posts/2015-05-10-servant-0.4-released.html

Table of contents

Since the last major release, a lot happened in and around servant. Definitely enough to justify a new release. This post announces new releases of all the servant packages, with many local changes but also some major ones that affect all packages. You can find the detailed changelogs at the end of this post, but here are a few major features you may want to learn about. This website also features a new tutorial that explains how to use servant from scratch.

Multiple content-type support

servant combinators are not JSON-centric anymore.

If you had an API type like the following with servant 0.2.x:

You now have to change it to:

Wherever applicable (i.e., ReqBody and all the combinators that correspond to an HTTP method), you can now specify all the content types in which you want to want to be able to encode/decode values. As you can see, we use the DataKinds GHC extension to let you specify a type-level list of content-types, which are simple dummy types:

In servant-server, a list of these content-types as the first argument of a method gets translated into a set of constraints on the return type:

Which have unsurprising instances:

Thus, servant checks at compile-time that it really can serialize your values as you describe. And of course, it handles picking the appropriate serialization format based on the request’s “Accept” header for you.

(For ReqBody, deserialization is involved. For servant-client, the logic goes the other way around - serialization for ReqBody, deserialization for methods.)

servant-blaze and servant-lucid

Declaring new content-types, and the associated constraints for them, is quite easy. But to make it easier still, we are also announcing two new packages: servant-blaze and servant-lucid. To use them, just import their HTML datatype:

And User will be checked for the appropriate (e.g. ToHtml) instance.

Response headers

There was no easy way so far to have handlers add headers to a response. We’ve since come up with a solution that stays true to the servant spirit: what headers your response will include (and what their types are) is still enforced statically:

servant-docs and servant-client are also response-header aware.

Our current solution isn’t something we are entirely happy with from an internal persepctive. We use overlapping instances for all the handlers, which some might think is already a problem. But more concretely, there’s the threat of an exponential blowup in the number of instances we have to declare. And that can be a problem for end users too, if they decide to further modify behavior via a similar mechanism. But these things thankfully don’t seem to pose any immediate problems.

Running handlers in other monads than EitherT

An often-requested feature has been easy use of datatypes/monads besides EitherT. Now we believe we have a good story for that (thanks in large part to rschatz). To convert from one datatype to another, all you need to do is provide a natural transformation between them. For example:

The new ServerT type synonym takes an extra paramer that represents what datatype/monad you are using over your handlers (instead of EitherT ServantErr IO).

(Note that we also provide a number of pre-existing Nats, which are an instance of Category. We could have used

readerServer = enter (generalizeNat . (runReaderTNat "hi")) readerServerT

instead (with . being from Control.Category).)

Note that the datatypes you can use now don’t even need to be monads!

Left

We also changed the default type of handlers from EitherT (Int,String) IO a to EitherT ServantErr IO a. Now it is possible to return headers and a response body in the Left case.

We also now export function errXXX (where XXX is a 300-599 HTTP status code) with sensible reason strings.

BaseUrl

We also changed the client function from servant-client so that, instead of returning various functions that each take a BaseUrl argument (often in inconvenient argument positions), the client function itself takes a BaseUrl argument, and the functions it returns don’t. So the type of client went from

To

Complete CHANGELOGs

Website

We also decided to switch to hakyll in order to be able to have a blog as well as some static pages that collect tips and tricks that people have found. We also used this opportunity to rewrite the getting started into a more informative tutorial, now available here.

Conclusions

As you can see, more and more information is getting encoded statically - the types are becoming a pretty rich DSL. In order to keep the noise down, do what you normally do: abstract away common patterns! If your endpoints always return the same content-types, make aliases:

There’s still an outstanding issue with the errors servant returns when a request doesn’t get handled. For example, if the path of a request, but not the method nor the request body, match, rather than returning a 405 (Method Not Allowed) we return a 400 (Bad Request), which is not the desired behavior. Andres Löh made some great suggestions for how to improve our routing time complexity, and hopefully we can integrate a fix for this issue when we tackle that.

We also merged our repos into servant. Please use that repo exclusively for PRs and issues (we’ll get rid of the others eventually).

Special thanks to the Anchor team from Australia, Matthew Pickering, Daniel Larsson, Phil Freeman, Matthias Fischmann, rschatz, Mateusz Kowalczyk, Brandon Martin and Sean Leather who’ve contributed from little fixes to whole new features. Several companies are now running servant-powered web applications.

]]> Sun, 10 May 2015 00:00:00 UT https://haskell-servant.github.io/posts/2015-05-10-servant-0.4-released.html servant developers
 
Original Source | Taken Source