HStringTemplate: An Elegant, Functional, Nifty Templating Engine for Haskell.

HStringTemplate is a port of Terrence Parr’s lovely StringTemplate engine to Haskell.

It is available, cabalized, at:
darcs get http://code.haskell.org/HStringTemplate/

As interest has grown in using Haskell for web applications, there has been an increasing buzz about the need for a good templating engine in Haskell. Why might we need this? After all, Haskell has lovely combinator libraries for generating HTML programmatically, enforcing good form through its type system. But sometimes, we don’t want well-formed HTML. We want the ugly stuff that floats around to deal with eight varieties of browser incompatibilities and the latest silly ajax trick. Or sometimes we’re working with a team of graphic designers, and they want to work in almost-HTML. Or sometimes we just want to be able to change the design of a web application on the fly, completely independent of our program logic, and of, heavens forbid, recompiling and possibly messing with a live application.

So template engines are popular, and indeed, considered a key part of most web frameworks out there. One problem — they’re mainly awful, imperatively-conceived behemoths that capriciously mix program logic with display and, consequently, entail a great deal of overhead. Enter StringTemplate, a nifty and fairly-well developed template format that’s both pure and functional, and therefore pretty much the only one of its kind. Indeed, it also seems to be getting heavy use in code generation because its paradigm maps neatly to traversing parse-trees.

HStringTemplate is not feature-complete, and indeed is only at version 0.1. But it should implement pretty much everything you’ll find here, only nicer, because it’s in Haskell. There are scads of different recursive constructs and ways to handle inclusion and inheritance. Furthermore, HStringTemplate handles conditionals, and also a very Haskellish implementation of custom rendering.

Templates can be constructed that return strings, ShowSs, bytestrings, or even pretty printer Docs that handle wrapping, indentation, and fill elegantly. Even better, these templates are parsed and compiled only once, after which point there isn’t a syntax tree anymore, just a function that operates on the environment of attributes that have been passed to it.

Ok. Enough talk. Let’s look at a sample GHCi session. Note that when defining “hello” we have to give the signature explicitly, as it’s not clear until later what type of StringTemplate we’re expecting.

> let hello = newSTMP "something $foo;separator='; '$ something" :: StringTemplate String
> toString $ setAttribute "foo" "SomethingElse" hello
"something SomethingElse something"
> toString $ setAttribute "foo" ["a","b","c"] hello
"something a; b; c something"
> toString $ setAttribute "foo" ([1..10]::[Double]) hello
"something 1.0; 2.0; 3.0; 4.0; 5.0; 6.0; 7.0; 8.0; 9.0; 10.0 something"

And that should be enough to get you started! Be sure to check the haddocks as well, which cover the API in some more detail.

Where I take it from here depends in part on what sort of response I get, so patches, gripes, API comments and feature requests are all more than welcome.

Meanwhile, I’ve learned quite a bit doing this, and suspect that once the benchmarks are in, this will in fact turn out to be a fairly lean and mean implementation compared to the Java one. As a matter of fact, it currently stands at, excluding tests, 414 lines of code. The Java version, admittedly somewhat more featureful, runs in the vicinity of 12,000! Over the next few weeks, I plan to blog about some of my “aha” moments, mainly involving monoids and their many delicious instances.

7 Comments »

  1. Johan Tibell said

    After reading Duncan’s post about how command line flags are monoids I’d be very interested in reading about other areas where monoids are useful!

  2. […] bookmarks tagged elegant HStringTemplate: An Elegant, Functional, Nifty Tem… saved by 1 others     finch250 bookmarked on 01/22/08 | […]

  3. Hello,

    I am a newbie Haskell user and I am finding this library quite useful, thanks.

    How about changing:

    setAttribute “key” “value” template

    to

    setAttribute template “key” “value”

    to better support currying?

  4. Dietrich Epp said

    In response to George, it took a little time for me to get used to the most elegant way to order function arguments. Take a look at the types in Data.Map, for example, insert is k -> a -> Map k a -> Map k a. This order supports currying of the template, so I can do:

    setMyAttributes = setAttribute “key1” “value1” . setAttribute “key2” “value2”

    Instead of:

    setMyAttributes t = setAttribute (setAttribute “key2” “value2” t) “key1” “value1”

  5. Artyom Shalkhakov said

    It looks like this templating system completely lacks computation of any kind (you can’t add two numbers within template, can you?).

    I find this somewhat confusing. Do you know of XSLT? It looks pretty much the same (no side-effects, support for recursive template substitution, etc.), except for many-many details (syntax, functions, etc.). :)

    Do you think it is better to compute everything outside of templates? And how about treating output as a document (not a raw string)? I suppose it would reduce the number of common syntactical errors, as well as provide some output validation.

  6. […] HStringTemplate is a Haskell port of Terence Parr’s StringTemplate engine (originally for Java but also available for C# and Python).  StringTemplate is a templating engine along the lines of Apache Velocity but is more restrictive in what processing it permits templates to perform.  Specifically, it strictly enforces separation between model and view.  It is not possible for a template to cause side-effects elsewhere (no database updates, etc.).  StringTemplate can be used for generating any kind of text output, not just XML/HTML.  In fact, one of its principal uses is as a code generator for ANTLR. […]

  7. gwern said

    http://code.haskell.org/HStringTemplate/dist/doc/html/hstringtemplate/Text-StringTemplate.html is broken link. Perhaps link to something like http://hackage.haskell.org/packages/archive/HStringTemplate/0.6.5/doc/html/Text-StringTemplate.html ?

RSS feed for comments on this post · TrackBack URI

Leave a comment