The heterocephalus package

[Tags:library, mit, test]

Recent front end development tools and languages are growing fast and have quite a complicated ecosystem. Few front end developers want to be forced use Shakespeare templates. Instead, they would rather use node-friendly engines such that pug, slim, and haml. However, in using these template engines, we lose the compile-time variable interpolation and type checking from Shakespeare.

Heterocephalus is intended for use with another feature rich template engine and provides a way to interpolate server side variables into a precompiled template file with forall, if, and case statements.

[Skip to Readme]


Versions, 1.0.0,,,,,,,,,,,
Change log
Dependencies base (>=4.7 && <5), blaze-html (>=0.8 && <0.10), blaze-markup (>=0.7 && <0.9), containers (==0.5.*), dlist (>=, mtl, parsec (==3.1.*), shakespeare (==2.0.*), template-haskell (>=2.7 && <3), text (==1.2.*), transformers [details]
License MIT
Copyright 2016 Kadzuya Okamoto
Author Kadzuya Okamoto
Category Web
Home page
Source repository head: git clone
Uploaded Mon Jun 5 08:39:35 UTC 2017 by arowM
Distributions LTSHaskell:, NixOS:, Stackage:, Tumbleweed:
Downloads 450 total (32 in the last 30 days)
0 []
Status Docs available [build log]
Last success reported on 2017-06-05 [all 1 reports]
Hackage Matrix CI




Maintainer's Corner

For package maintainers and hackage trustees

Readme for heterocephalus

Readme for heterocephalus-

Build Status Hackage Stackage LTS Stackage Nightly


Heterocephalus template engine

A type-safe template engine for working with popular front end development tools.

Any PRs are welcome, even for documentation fixes. (The main author of this library is not an English native.)

Who should use this?

If you are planning to use Haskell with recent web front-end tools like gulp, webpack, npm, etc, then this library can help you!

There are many Haskell template engines today. Shakespeare is great because it checks template variables at compile time. Using Shakespeare, it's not possible for the template file to cause a runtime-error.

Shakespeare provides its own original ways of writing HTML (Hamlet), CSS (Cassius / Lucius), and JavaScript (Julius). If you use these original markup languages, it is possible to use control statements like forall (for looping), if (for conditionals), and case (for case-splitting).

However, if you're using any other markup language (like pug, slim, haml, normal HTML, normal CSS, etc), Shakespeare only provides you with the Text.Shakespeare.Text module. This gives you variable interpolation, but no control statements like forall, if, or case.

Haiji is another interesting library. It has all the features we require, but its templates take a very long time to compile with GHC >= 7.10.

Heterocephalus fills this missing niche. It gives you variable interpolation along with control statements that can be used with any markup language. Its compile times are reasonable.


Here are the main features of this module.

  • DO ensure that all interpolated variables are in scope

  • DO ensure that all interpolated variables have proper types for the template

  • DO expand the template literal on compile time

  • DO provide a way to use forall, if, and case statments in the template

    Text.Shakespeare.Text.text has a way to do variable interpolation, but no way to use these types of control statements.

  • DO NOT enforce that templates obey a peculiar syntax

    Shakespeare templates make you use their original style (Hamlet, Cassius, Lucius, Julius, etc). The Text.Shakespeare.Text.text function does not require you to use any particular style, but it does not have control statements like forall, if and case.

    This makes it impossible to use Shakespeare with another template engine such as pug in front end side. It is not suitable for recent rich front end tools.

  • DO NOT have a long compile time

    haiji is another awesome template library. It has many of our required features, but it takes too long to compile when used with ghc >= 7.10.

  • DO NOT provide unneeded control statements

    Other template engines like EDE provide rich control statements like importing external files. Heterocephalus does not provide control statements like this because it is meant to be used with a rich front-end template engine (like pug, slim, etc).


You can compile external template files with the following four functions:

  • compileTextFile: A basic function that embeds variables without escaping and without default values.
  • compileTextFileWithDefault: Same as compileTextFile but you can set default template values.
  • compileHtmlFile: Same as compileTextFile but all embeded variables are escaped for html.
  • compileHtmlFileWithDefault: Same as compileHtmlFile but you can set default template values.

For more details, see the latest haddock document.

Checking behaviours in ghci

To check the behaviour, you can test in ghci as follows. Note that compileText and compileHtml are used for checking syntaxes.

$ stack install heterocephalus  # Only first time
$ stack repl --no-build --no-load
Prelude> :m Text.Heterocephalus Text.Blaze.Renderer.String
Prelude> :set -XTemplateHaskell -XQuasiQuotes
Prelude> let a = 34; b = "<script>"; in renderMarkup [compileText|foo #{a} #{b}|]
"foo 34 <script>"
Prelude> let a = 34; b = "<script>"; in renderMarkup [compileHtml|foo #{a} #{b}|]
"foo 34 &lt;script&gt;"


The Text.Heterocephalus module provides two major features for use in template files: variable interpolation and control statements.

Variable interpolation

A Haskell variable can be embedded in the template file with the #{foo} syntax. The value of the variable will be injected in at run time.

Basic usage

All of following are correct (this assumes that you have already declared the var variable in your Haskell program and it is in scope):

#{ var }
#{  var}
#{var  }
#{ var  }

The variable must be an instance of Text.Blaze.ToMarkup.

Advanced usage

You can use functions and data constructors as well.

#{ even num }
#{ num + 3 }
#{ take 3 str }
#{ maybe "" id (Just b) }

Control statements

Only two type of control statements are provided.


%{ forall x <- xs }
%{ endforall }

%{ forall (k,v) <- kvs }
#{k}: #{v}
%{ endforall }


%{ if even num }
#{num} is even number.
%{ else }
#{num} is odd number.
%{ endif }
%{ if (num < 30) }
#{ num } is less than 30.
%{ elseif (num <= 60) }
#{ num } is between 30 and 60.
%{ else }
#{ num } is over 60.
%{ endif }


%{ case maybeNum }
%{ of Just 3 }
num is 3.
%{ of Just num }
num is not 3, but #{num}.
%{ of Nothing }
num is not anything.
%{ endif }
%{ case nums }
%{ of (:) n _ }
first num is #{n}.
%{ of [] }
no nums.
%{ endif }

Why we do not provide maybe and with?


Discussions about this topic is on issue #9.

Why "heterocephalus"?

"Heterocephalus" is the scientific name of the naked mole-rat.