LoCo Day 4

Another horrifically unproductive day, mostly spent searching for and reading documentation and tutorials for the libraries I’m trying to use, in the hopes of figuring out the right way to use them together.

I think the mistake I’ve been making is the assumption that I want to be using a MonadReader to expose session and request information to the Heist templates I’ll be using to piece together web pages. All of the Heist tutorials and blog posts I’ve seen hand-wave the issue of accessing request-specific data in templates and splices by supposing an application monad exists that provides an operation to get at that information. I had originally taken that to mean that I should use a ReaderT to package up that sort of information and add it to the monad stack I’ve pieced together out of Happstack, web-routes, and Heist. However, sticking a ReaderT into the stack throws the compiler into a fit, since it winds up hiding some of the monad typeclasses below it in the stack. For instance, Happstack doesn’t provide the plumbing for ReaderT to lift ServerMonad operations up, and I don’t know whether that’s a deliberate design decision or an oversight. There doesn’t seem to be a feasible place to stick the ReaderT into the stack that doesn’t cause problems somewhere.

So, what I think I’ll try to do is give up on ReaderT entirely for this, and instead pass the Session object and any other resource handles I need to worry about as function arguments (possibly encapsulated in some Context object so I have only one thing to pass around instead of a bunch) until they get to the actual request routing function. In there, I’ll create splices out of the session information for the templates to use, passing them to Heist at the same time I tell it which template I want to render. This is slightly complicated by the fact that the happstack-heist module, which provides the plumbing between Happstack and Heist, doesn’t provide a wrapper for the Heist function that lets you invoke a template with extra splices. Fortunately, it doesn’t look like it’d be difficult to reimplement that bit of plumbing myself. I’m still not certain this is the “correct” way to do things, but there’s a chance it will work, which is better than my approach so far.

I had also considered giving up on Heist and using some other mechanism for generating web pages. Blaze would have the advantage of better type safety since the HTML-generating code would be part of the program, but then I’d be stuck using Blaze functions to construct the pages instead of writing something that actually looks like HTML. HSP would in theory solve this by letting you write XML directly in the program and use preprocessing magic to translate it into Haskell code at compile time. However, HSP has the crippling flaw of being effectively undocumented, other than a bit of API documentation and pointers to a ten-year-old thesis written about it. Other templating engines seem to be merely string-based, which makes me concerned about the possibility of accidental cross-site scripting attacks.

It’d be great if there were some well-documented, simple-but-not-trivial example out there of something using Happstack, Heist, and web-routes together, but I haven’t managed to come across it yet. I guess I’ll keep stumbling along tomorrow.