TemplateHaskell


References:


Q, the quotation monad, seems to be the main thing.

General:

(E: Expresssion, P: Pattern, L: Literal?, T: type?)

ExpQ is an alias for Q Exp

Example use:

Clash.Prelude Language.Haskell.TH> runQ [| \x -> 1 |]
LamE [VarP x_0] (LitE (IntegerL 1))

Clash.Prelude Language.Haskell.TH> :t it
it :: Language.Haskell.TH.Exp
Prelude> :set -XTemplateHaskell
Prelude> import Language.Haskell.TH.Syntax
Prelude Language.Haskell.TH.Syntax>

Quoting with quotes

Non-type values can be quoted with one single quote:

Prelude Language.Haskell.TH.Syntax> :t 'id
'id :: Name

Prelude Language.Haskell.TH.Syntax> 'id
GHC.Base.id

Prelude Language.Haskell.TH.Syntax> :t id
id :: a -> a

Type values can be quoted with two single quotes:

Prelude Language.Haskell.TH.Syntax> ''Bool
GHC.Types.Bool

Prelude Language.Haskell.TH.Syntax> :t ''Bool
''Bool :: Name

Prelude Language.Haskell.TH.Syntax> 'Bool
<interactive>:31:1: error:
    • Not in scope: data constructor ‘Bool’
    • In the Template Haskell quotation 'Bool

Builtins

Prelude Language.Haskell.TH.Syntax> :t LamE
LamE :: [Pat] -> Exp -> Exp

Prelude Language.Haskell.TH.Syntax> :t VarP
VarP :: Name -> Pat

The TemplateHaskell extension got to enable for some stuff to work:

Prelude Language.Haskell.TH.Syntax> runQ [e| Just x |]
<interactive>:20:18: error: parse error on input ‘]’

Prelude Language.Haskell.TH.Syntax> :set -XTemplateHaskell
Prelude Language.Haskell.TH.Syntax> runQ [e| Just x |]
AppE (ConE GHC.Maybe.Just) (UnboundVarE x)

Stage restriction

varname is used in a top-level splice, quasi-quote, or annotation,
        and must be imported, not defined locally

Conventions

Last letter of variable names usually follow this convention:

Info

Some Syntax

From https://markkarpov.com/tutorial/th.html:

Declaration [d ] Q [Dec]
Expression [e ] Q Exp
Typed expression [
Type [t ] Q Type
Pattern [p ] Q Pat

Misc

λ> import Language.Haskell.TH
λ> a = mkName "hi"
λ> :t a
a :: Name