web-routes is a system for implementing type-safe web-routes in Haskell web applications. In
part 1, we saw the basics of how to use web-routes.
In part 1, we used template haskell to automatically derive the mapping between the url string and the url type. This makes development very easy, but the automatically derived urls are not all that visually appealing.
In this part, we introduce a way to manually specify the mapping between the url type and the url string. This gives the developer 100% control over the mapping. Up to now, the problem with creating a manual mapping has been that you had to implement the specification twice. You had to write a show function to turn a url type into a url string, and a read function to turn a url string into a url type. These functions are basically inverses of each other, both following the same spec.
What we really want to do is write the spec once and automatically extract the printer and parser from the spec. That way we can be sure they are inverses of each other, and we do not have to repeat ourselves. And we do not have to repeat ourselves. Because that is annoying.
Fortunately, Sjoerd Visscher and Martijn van Steenbergen figured out exactly how to do that and published a proof of concept library know as
Zwaluw. With permission, I have refactored their original library into two separate libraries:
boomerang and
web-routes-boomerang.
boomerang is a general purpose, standalone invertible parser library.
web-routes-boomerang adds glue code around
boomerang so that it can be used to with
web-routes.
Using
boomerang we can take a route like this one:
> data Sitemap
> = Home
> | Article ArticleId
> | UserOverview
> | UserDetail Int String
> deriving (Eq, Ord, Read, Show, Data, Typeable)
>
a specify a route map like this:
> sitemap :: Router Sitemap
> sitemap =
> ( rHome
> <> rArticle . (lit "article" </> articleId)
> <> lit "users" . users
> )
> where
> users = rUserOverview
> <> rUserDetail </> int . lit "-" . anyString
which defines a mapping like this:
| url | | type |
| / | <=> | Home |
| /article/int | <=> | Article int |
| /users | <=> | UserOverview |
| /users/int-string | <=> | UserDetail int string |
The
sitemap function looks like a ordinary parser. But, what makes it is exciting is that it also defines the pretty-printer at the same time.
For more in-depth details, see the
relevant section of the Happstack Crash Course. If you just want to play with
boomerang then
start here.