When I program in my spare time, I usually do enough work to cover all of the interesting parts, and then abandon the project to move onto something new. I guess this is because I put more of a focus on the problem than the finished result.
Because of this, it’s something of a pleasant surprise that I am continuing to work on my Haskell HTTP server over a month after I started on it. I’ve decided on a name, Haffle, and I’ve just finished version 0.0.3. Haffle 0.0.3 can read POST variables and GET query strings, so it’s starting to become almost useful.
I’m a little dissatisfied with the libraries available for authoring web pages in Haskell. I want something that takes full advantage of Haskell’s do-notation to produce simple, readable code. Something like this:
main = httpServe 8080 $ do GET "/hello" ==> index index :: Reader HttpRequest (HttpResponse -> IO HttpResponse) index = do name <- param "name" setHeader "Content-Type" "text/plain" output "Hello " output name
I’m still a way from finishing it, but I’ve managed to create a HTTP request parser and a basic server. I’m aiming for a initial 0.0.1 release that will allow me to specify fixed outputs for any valid HTTP request:
main = httpServe 8080 (output "Hello World")
From there, I hope to add features with each release, until I have something usable. The code will be available under a MIT license.
As a general rule, I find I’m not happy with a software project until at least the third ground-up rewrite. Rewriting is usually discouraged in business, and not without some good reason. But in my spare time, I often find myself happily refactoring my code, each design better than the last, but never quite getting any further before I spot some flaw that inspires another redesign.
Haskell seems to encourage this constant honing, not just for complex modules or sophisticated libraries, but even for the smallest function. It’s refactoring in miniature; a sort of code bonsai.
I was recently trying to create a netstrings implementation for Haskell, and I started off with a function that would strip the first length indicator off. So for instance, “5:hello,” would become (5, “hello,”)
readLength :: String -> (Int, String) readLength s = (read n, tail s') where (n, s') = break (== ':') s
This was my first attempt. Did it work? Yep! Could I do better? Maybe…
I was recently faced with the task of turning a table of database results of the form:
A B D A B E A C F A C G
Into an XML structure like this:
<A> <B> <D/> <E/> </B> <C> <F/> <G/> </C> </A>
The language I originally used to solve this problem was C# 1.0, which involved a while loop and a lot of conditions to check state. This is a rather inelegant solution; what I’d like to have done is taken a step back, and written a more generic function that converts any arbitrary table of results into its corresponding tree. C# lacks the tools to do this with any ease, but for Haskell, such abstractness is second nature.