Compile-time evaluation
- GHC language extensions
- Splicing
- Runtime checking with
error - Compile-time checking with splices
- Runtime checking with
fail - Using
MonadFailin a splice
- Runtime checking with
- Quasi-quotation
- Complete example
If you replace an expression expr with $(lift (expr)), then that expression will be evaluated during compilation. The type of expr must have an instance of the Lift class, which comes from the template-haskell package, and the TemplateHaskell extension must be enabled.
If you have reason to be concerned that evaluation of expr may fail, this technique has the benefit of giving you a compilation failure instead of producing a program that fails by throwing an exception at runtime. For example, in this article we define a type named DigitThe example in this article is based on the d10 package. Other libraries that use this technique include modern-uri and aeson-qq. which is a newtype for Int – with the restriction that the value must be between 0 and 9 – and we discuss ways to write constant expressions in Haskell signifying “the digit n” such that “the digit 5” compiles but “the digit 12” does not.
For further convenience, if the expression expr is of the form f "..." (some function applied to a string literal), then you may want to consider defining a quasi-quoter.
g :: QuasiQuoter
g = QuasiQuoter { quoteExp = \str -> lift (f str) }Then instead of writing $(lift (f "...")), you can equivalently write [g|...|]. To use the quasi-quoter, the QuasiQuotes extension must be enabled.
GHC language extensions
These features require some GHC language extensions:
An expression of the form
$(...)is called a splice. It is enabled by theTemplateHaskellextension. When a library has a module containing functions that are designed to be used in splices, that module is conventionally namedTH.An expression of the form
[quoter|string|]is called a quasi-quotation. It is enabled by theQuasiQuotesextension. When a library has a module containing quasi-quoters, that module is conventionally namedQQ.You may also need the
DeriveLiftextension, Alternatively, you may deriveGenericand usegenericLiftfrom thelift-genericspackage instead oflift. which lets automatically derive aLiftinstance for a type that you have defined.

