Subject: On the state of Haskell web frameworks
Date: Sunday 19th September 2010 10:49:57 UTC (over 8 years ago)
For what it's worth, I thought I'd throw a simple web app into the mix, hpaste.org: * Address http://hpaste.org/ * Source http://github.com/chrisdone/amelie The notable thing about this application is it's easy to see all the requirements ("small libraries"): 1. CGI/FastCGI: I needed a way to talk to the web, I chose CGI/FastCGI. The CGI library is quite general and small. 2. highlighting-kate: I needed to do syntax highlighting. Notice how it's just a few lines in an isolated module: http://github.com/chrisdone/amelie/blob/master/src/Amelie/Highlight.hs 3. Takusen: I needed to talk to a PostgreSQL database to save/read pastes, just a few lines (for setup) in an isolated module: http://github.com/chrisdone/amelie/blob/master/src/Amelie/DB.hs 4. ConfigFile: I needed a way to store the service's settings in a configuration file. Again, just a few lines in an isolated module: http://github.com/chrisdone/amelie/blob/master/src/Amelie/Config.hs 5. blaze-html/xhtml: I needed a way to build HTML inside my program. 6. formlets: I needed a way to generate and validate forms (e.g. the paste form). 5 and 6 are used in the HTML module: http://github.com/chrisdone/amelie/blob/master/src/Amelie/HTML.hs All of these libraries are perfect, they do one thing and do it well. I just imported them and they did the work for me. You can see also how they are modules in themselves, not interdependent as part of some grand framework. It seems that with good libraries, the architecture of your web app just designs itself. Personally I've always thought the "MVC" approach isn't particularly novel and follows naturally from good design. I'm not saying mine is good design, but without putting much conscious thought towards it, I've ended up with a DB module (model), a Pages module (controller) and a HTML module (view). To make this into the MVC approach, I'd just rename them to Model.hs, Controller.hs and View.hs. The things that I had to implement myself are as follows: 7. URI routing: http://github.com/chrisdone/amelie/blob/master/src/Amelie/Routes.hs How to receive requests and map that into a page + parameters to that page (e.g. paste/pid/30196 -> pastePage [("pid","30196")]), how to *generate* a URL with parameters. And how to generate a *pretty* URL: http://github.com/chrisdone/amelie/blob/master/src/Amelie/Links.hs A URL that maps back to a normal URL (e.g. http://hpaste.org/30196/half_a_proof is actually rewritten by nginx to http://hpaste.org/paste/id/30196). I think there probably are quite a few URI routing libraries out there but I only gave it a cursory glance. 8. Simple template writing. http://github.com/chrisdone/amelie/blob/master/src/Amelie/Templates.hs In fact I found that tibbe already wrote something to do this: http://hackage.haskell.org/package/template but I didn't end up using it for some reason. Maybe because everything has to be Text and I couldn't be bothered littering my code with string conversions all over the place. Turned out I had to do that anyway. Converting between String and ByteString and lazy ByteString and now Text is a real pain but you have to do it because all these different libraries decided to use a particular type. (At least some let you implement a Stringable class.) I will probably eventually just replace the templating code with tibbe's or go the full hog and use HStringTemplate. It's all the same idea, just more or less engineered. I'm interested in your thoughts and ideas. If you have any hpaste-size web applications that you have available online to read that you can maybe summarise and evaluate in the same way I have above, maybe that can spark some interesting discussion. Cheers!