Search code examples
haskellhaskell-snap-frameworkheist

Passing data directly into templates in compiled Heist (Haskell)?


I use compiled Heist. My splices only do run-time work (no load-time work). I have a template.tpl like this:

<html>
<head>
    <title><titleSplice/></title>
</head>
<body>
    <bodySplice/>
</body>
</html>

This is how I do things:

  • Within the Snap action for a /:param route, I use renderTemplate heistState "template" to obtain a MyHeistRuntimeMonad Builder.
  • I can pass the :param value to my splice by putting it into my runtime monad via ReaderT: type MyHeistRuntimeMonad = ReaderT String IO. (Where the String is for the passed in :param value.)

And that is my problem. The only way to pass data from my routes to my splices is through the heist runtime monad. This makes things a bit complicated. My questions:

  1. Is there no alternative to renderTemplate that allows me to pass data directly to the template? For example, something like this: renderTemplate' "template" [("titleSplice", "myTitle"), ("bodySplice", "myBody")].
  2. If this is not possible, why not? I'm just wondering why things were designed the way they were. I don't quite get it.

Solution

  • The example that you're focusing on with the runtime data of [("titleSplice", "myTitle"), ("bodySplice", "myBody")] is MUCH less powerful than the model that Heist exposes. Your model is simple tag name substitution. Heist's splice model is Node -> m [Node]. This allows it to do very powerful things like the cache tag, the markdown tag, and even head merging with the html tag.

    The monad transformer approach Heist uses was a simple and obvious implementation that makes all runtime data accessible to splices. It also thinks of splices as a universal API provided by the backend that can be used anywhere by front end designers. Are other formulations possible? I'm sure there are. But this one is simple and powerful.

    Your formulation is also very template specific. If a designer wanted to add some new kind of data to a page, you would have to change the Haskell code to accommodate that. With Heist's approach no Haskell code change would be necessary. This gives designers a lot of power to change things in a very decoupled manner.