1 What is Template Haskell?

Template Haskell is an extension to Haskell 98 that allows you to do type-safe compile-time meta-programming, with Haskell both as the manipulating language and the language being manipulated.

Intuitively Template Haskell provides new language features that allow us to convert back and forth between concrete syntax, i.e. what you would type when you write normal Haskell code, and abstract syntax trees. These abstract syntax trees are represented using Haskell datatypes and, at compile time, they can be manipulated by Haskell code. This allows you to reify (convert from concrete syntax to an abstract syntax tree) some code, transform it and splice it back in (convert back again), or even to produce completely new code and splice that in, while the compiler is compiling your module.

3 Template Haskell tutorials and papers

One reader said "These docs are *brilliant* ! Exactly what I need to get an understanding of TH."

(Note: These documents are from the Wayback machine because the originals disappeared. They're public documents on Google docs, which shouldn't require logging in. However, if you're asked to sign in to view them, you're running into a known Google bug. You can fix it by browsing to Google, presumably gaining a cookie in the process.)

I am writing Template Greencard - a reimplementation of GreenCard using TH. Many bits work out really nicely. A few bits didn't work so nicely - once I get some time to think, I'll try to persuade the TH folk to make some changes to fix some of these. -- AlastairReid

Following other FFI tools developers, I see some future for Template HSFFIG, especially when it comes to autogenerate peek and poke methods for structures defined in C; may be useful for implementation of certain network protocols such as X11 where layout of messages is provided as C structure/union declaration. - 16 Dec 2005 DimitryGolubovsky

I am working on functional metaprogramming techniques to enhance programming reliability and productivity, by reusing much of the existing compiler technology. Template Haskell is especially interesting for me because it permits to check size information of structures by the compiler, provided this information is available at compile time. This approach is especially appropriate for hardware designs, where the structures are fixed before the circuit starts operating. See our metaprogramming web page at http://www.infosun.fmi.uni-passau.de/cl/metaprog/ -- ChristophHerrmann(http://www.cs.st-and.ac.uk/~ch)

The ability to use things defined at the toplevel of a module from splices in that same module (would require multi-stage compilation, as opposed to the current approach of expanding splices during typechecking)

Section 3 (deriving instances of classes)

First-class reification (the

reify

function)

A way to discover whether a data constructor was defined infix or prefix (which is necessary to derive instances for

He says something to the effect that a pattern-matching form of the quotation brackets would be cool if it was expressive enough to be useful, but that this would be hard. (Don't expect this anytime soon.)

Section 5 (fraskell)

Type information for quoted code (so that simplification can be done safely even with overloaded operations, like, oh,

9 Tips and Tricks

9.1 What to do when you can't splice that there

When you try to splice something into the middle of a template and find that you just can't, instead of getting frustrated about it, why not use the template to see what it would look like in longhand?

Say I want to find out what I need to do to splice in the types for an instance declaration for the SignConversion class, so that I can declare instances for Int8 with Word8 through Int64 with Word64. So, I start up good-ol' GHCi and do the following:

9.2 What can reify see?

When you use reify to give you information about a Name, GHC will tell you what it knows. But sometimes it doesn't know stuff. In particular

Imported things. When you reify an imported function, type constructor, class, etc, from (say) module M, GHC runs off to the interface file M.hi in which it deposited all the info it learned when compiling M. However, if you compiled M without optimisation (ie -O0, the default), and without -XTemplateHaskell, GHC tries to put as little info in the interface file as possible. (This is a possibly-misguided attempt to keep interface files small.) In particular, it may dump only the name and kind of a data type into M.hi, but not its constructors.

Under these circumstances you may reify a data type but get back no information about its data constructors or fields. Solution: compile M with

-O, or

-fno-omit-interface-pragmas (implied by -O), or

-XTemplateHaskell.

Function definitions. The VarI constructor of the Info type advertises that you might get back the source code for a function definition. In fact, GHC currently (7.4) always returns Nothing in this field. It's a bit awkward and no one has really needed it.

10.4 Handling Options with Templates

A common idiom for treating a set of options, e.g. from GetOpt, is to define a datatype with all the flags and using a list over this datatype:

data Options = B1 | B2 | V Integer
options =[B1, V 3]

While it's simple testing if a Boolean flag is set (simply use "elem"), it's harder to check if an option with an argument is set. It's even more tedious writing helper-functions to obtain the value from such an option since you have to explicitely "un-V" each. Here, Template Haskell can be (ab)used to reduce this a bit. The following example provides the module "OptionsTH" which can be reused regardless of the constructors in "Options". Let's start with showing how we'd like to be able to program. Notice that the resulting lists need some more treatment e.g. through "foldl".

10.5 Generic constructor for records

Currently I use GHC's Binary module to read them from files; it can handle
types like (Word8, (Word8, Word16)), but there was no easy way to generate
the correct amount of "uncurry" calls for automatically grabbing each element.

With Template Haskell, the instance declarations are now written as such:

instance Binary PGD where
get bh =do a <- get bh ; return$$(constrRecord PGD) a