Template Haskell is enabled by the -XTemplateHaskell
GHC extension. This extension enables all the syntactic features further detailed in this section. The full details on Template Haskell are given by the user guide.
A splice is a new syntactic entity enabled by Template Haskell, written as $(...)
, where (...)
is some expression.
There must not be a space between $
and the first character of the expression; and Template Haskell overrides the parsing of the $
operator - e.g. f$g
is normally parsed as ($) f g
whereas with Template Haskell enabled, it is parsed as a splice.
When a splice appears at the top level, the $
may be omitted. In this case, the spliced expression is the entire line.
A splice represents code which is run at compile time to produce a Haskell AST, and that AST is compiled as Haskell code and inserted into the program
Splices can appear in place of: expressions, patterns, types, and top-level declarations. The type of the spliced expression, in each case respectively, is Q Exp
, Q Pat
, Q Type
, Q [Decl]
. Note that declaration splices may only appear at the top level, whereas the others may be inside other expressions, patterns, or types, respectively.
An expression quotation is a new syntactic entity written as one of:
[e|..|]
or [|..|]
- ..
is an expression and the quotation has type Q Exp
;[p|..|]
- ..
is a pattern and the quotation has type Q Pat
;[t|..|]
- ..
is a type and the quotation has type Q Type
;[d|..|]
- ..
is a list of declarations and the quotation has type Q [Dec]
.An expression quotation takes a compile time program and produces the AST represented by that program.
The use of a value in a quotation (e.g. \x -> [| x |]
) without a splice corresponds to syntactic sugar for \x -> [| $(lift x) |]
, where lift :: Lift t => t -> Q Exp
comes from the class
class Lift t where lift :: t -> Q Exp default lift :: Data t => t -> Q Exp
Typed splices are similair to previously mentioned (untyped) splices, and are written as $$(..)
where (..)
is an expression.
If e
has type Q (TExp a)
then $$e
has type a
.
Typed quotations take the form [||..||]
where ..
is an expression of type a
; the resulting quotation has type Q (TExp a)
.
Typed expression can be converted to untyped ones: unType :: TExp a -> Exp
.
QuasiQuotes generalize expression quotations - previously, the parser used by the expression quotation is one of a fixed set (e,p,t,d
), but QuasiQuotes allow a custom parser to be defined and used to produce code at compile time. Quasi-quotations can appear in all the same contexts as regular quotations.
A quasi-quotation is written as [iden|...|]
, where iden
is an identifier of type Language.Haskell.TH.Quote.QuasiQuoter
.
A QuasiQuoter
is simply composed of four parsers, one for each of the different contexts in which quotations can appear:
data QuasiQuoter = QuasiQuoter { quoteExp :: String -> Q Exp, quotePat :: String -> Q Pat, quoteType :: String -> Q Type, quoteDec :: String -> Q [Dec] }
Haskell identifiers are represented by the type Language.Haskell.TH.Syntax.Name
. Names form the leaves of abstract syntax trees representing Haskell programs in Template Haskell.
An identifier which is currently in scope may be turned into a name with either: 'e
or 'T
. In the first case, e
is interpreted in the expression scope, while in the second case T
is in the type scope (recalling that types and value constructors may share the name without amiguity in Haskell).