hvac (short for http view and controller) has been my project for the last little while, and is finally in a fairly usable state, so I’m opening up the repo (darcs get http://community.haskell.org/~sclv/hvac/) for folks to play with and to get some feedback. While its not yet ready for hackage, the package as provided should be fully cabal installable. Documentation is available at http://community.haskell.org/~sclv/hvac/html_docs/hvac/
The aim of hvac is to provide an environment that makes the creation of lightweight fastcgi-based web applications as simple as possible, with an emphasis on concise, declarative style code, correct concurrent transactional logic, and transparency in adding caching combinators.
There are two included example programs, naturally neither of which is feature complete. They share a common login module of about 50 lines of code, excluding imports and templates.
The first program is a classic, greenspun-style message board with basic login functionality. It totals roughly 40 lines and tends to use just under 4mb of memory on my system.
The second is a wiki based on Pandoc and the PandocWiki code. The code totals roughly 30 lines (rendering borrowed from PandocWiki aside) and uses about 5mb of memory on my system.
hvac processes all requests in the STM monad, with some bells attached to properly interleave STM with session, database and filesystem operations such that they all conceptually occur together in a single transaction per request. Currently it is only fully tested with sqlite, but it should operate, modulo a few tweaks, with an database accessible via HDBC.
hvac is particularly designed to use the HStringTemplate library as an output layer, in a simple declarative fashion, and HStringTemplate has been improved in the process (about which more below). As the StringTemplate grammar is explicitly sub-turing, this ensures a clean separation of program logic from presentation, while providing a nonetheless fairly powerful language to express typical display tasks.
The included cache combinators, still experimental, should allow a simple and fine-grained control over the level of caching of various disk-bound operations. Phantom types are used to ensure that no functions that modify state may be cached.
To give a flavor of hvac code, the following is the complete (twenty lines!) source of the wiki controller (due to sql statements, some lines are rather long, and I’ve added a few odd breaks to make them work on this page):
wikiController tmpl = h |/ "login" *> login_plug tmpl <|> (h |/ "wiki" |\\ \pageName -> h |// "POST" *> withValidation [ ("contents", return) ] (\ [contents] -> do pageId <- selectVal "id from pages where name=?" [toSql pageName] maybe (addErrors [("Login","must be logged in.")] >> continue) (\user -> case fromSql pageId of Just (_::Int) -> execStat "insert into page_hist(pageId,contents,author) values(?,?,?)" [pageId, toSql contents, toSql . userName $ user] Nothing -> do execStat "insert into pages(name,locked) values(?,?)" [toSql pageName, toSql (0::Int)] pid <- selectVal "max(id) from pages"  execStat "insert into page_hist(pageId,contents,author) values(?,?,?)" [pid, toSql contents, toSql . userName $ user]) =<< getSes continue) <|> do pageId <- selectVal "id from pages where name=?" [toSql pageName] (join $ renderf (tmpl "showPage") ("pageName", pageName) "pageContents" |= selectRow "* from page_hist where pageId=? order by time desc limit 1" [pageId] )) <|> (redirect . ( ++ "/wiki/Index") =<< scriptName)
Future directions for work on hvac include: Stress testing for correctness of transactional logic and benchmarks. Exploration of various efficiency tweaks. Unit tests. Further development of the cache combinator API. Improvement of the example apps and addition of a few others (a blog maybe). Expansion of the library of validator functions. Exploration of transferring hvac to the standard FastCGI bindings (currently it uses a custom modified version to work properly with STM). Improvement of the database layer, particularly with regards to common paging functions. Creation of a set of simple combinators for generating CRUD (create read update delete) pages. Creation of a minimal set of standard templates (maybe).