8 May 2010 (updated 9 May 2010 at 08:09 UTC)
»
A monoid for server parties
Happstack is a Haskell web applications framework.
I hadn't played with it in a while but
Happstack 0.5.0 was recently released
so I decided to try it out. You can get it with
cabal:
$ cabal update
$ cabal install happstack
Happstack has a pretty detailed tutorial, which is actually a
self-hosted happstack site that you can cabal install
and dig around in. It takes a while though, so let's just get
into it. The tutorial doesn't actually start showing
any code until section 7,
first
shot at happstack. This shows you how to run a Hello World
server from Haskell's
REPLghci:
$ ghci
Prelude> import Happstack.Server
Prelude Happstack.Server> simpleHTTP (Conf 8080 Nothing) (return "Hello World!")
Then your http://localhost:8080/ should show a Hello World
message, ie. you can run this in another terminal:
$ curl -i http://localhost:8080/
HTTP/1.1 200 OK
Connection: Keep-Alive
Content-Length: 12
Content-Type: text/plain; charset=UTF-8
Date: Tue, 04 May 2010 01:02:31 GMT
Server: Happstack/0.5.0
Hello World!
A REPL is great for playing around, but some real code to read
for an example server is
ControllerBasic.hs.
At the top of that file we get hit with this:
mzero corresponds to a 404 and mzero `mappend` f = f,
while if f is not mzero then f `mappend` g = f.
That's not even code, it's a comment.
Like, omg why would anyone talk like that? lol
It's talking about a type called ServerPartT, which you can think of as
an abstract part of your web server, like the part that handles "everything under
/articles" or "all the images". If you connect a bunch of these together
you get your whole web server.
Anyway, it turns out that it's much more fun if you simply pronounce ServerPartT as
"Server Party":
So what's all this about monoids?
Mathematically speaking, a monoid is a simple party game that some data objects
can play when they get together. This is a mathematical definition in the
sense that mathematicians are fun at parties.
The rules of the game are just that you have some way of appending things together;
the tricky Haskell name for this is mappend, named after
the famous French mathematician
M. Append. Whenever you mappend two things together you get another thing
of the same type that can also be mappended. There's also an empty element
called mempty, or here called mzero(*).
So a monoid is just a way of saying how you connect things up. In terms of
ServerPartTs:
- mzero corresponds to a 404:
The empty part of your server is
404 Not Found;
ie. if your server contained
no application parts at all, it would just have to return 404 for any request. In
general if a ServerPartT can't handle the current request (eg. the ServerPartT
for images doesn't handle /articles then it'll act like mzero for that
request).
- mzero `mappend` f = f:
mappend is the way that you connect up two server parts. Basically you just try
server parts one after another: when a request comes along, if the first ServerPartT
can't handle it, ie. acts like mzero, then try the next ServerPartT
(and hey let's call it f).
- if f is not mzero then f `mappend` g = f:
On the other hand, if the first server part can handle the request,
ie. it does not return 404 and is not mzero, then use it and ignore all the
other ServerPartTs (call them g). The whole server is acting just like f
by itself!
The point is that because ServerPartT follows all the rules of the monoid party game,
you can suddenly use all the functions available in
Data.Monoid,
like mconcat which takes a whole list of objects and works out what would happen if they were all
mappended together. This allows you to simply make a list of ServerPartTs and use the first one
that doesn't return 404: you don't even need to write a function for evaluating your whole server, you can
just use the plain old boring mconcat from the base libraries!
The structure of monoids (stuff that can be appended) is pretty trivial, but very common. I highly recommend
sigfpe's
Haskell Monoids and their Uses
to learn about some other more general uses.
As for Happstack: it's obviously a bit deeper than your average web framework. In this article I've only looked at
the basic idea behind making a server; it has many more features for managing data, transactions and scaling.
So what do you think? Is the monoidal mumbo-jumbo useful or does it just add a layer of confusion?
Would servers really wear party hats to a ServerPartT?
(*) because ServerPartT is the awesome kind of monoid formed by the MonadPlus type class,
obviously.
Syndicated 2010-05-08 07:00:00 (Updated 2010-05-09 07:20:37) from Conrad Parker