Announcing template-haskell-lift and template-haskell-quasiquoter
Posted on by Teo Camarasu
Introductionπ
The template-haskell package has a large interface, which includes both stable and unstable parts.
The unstable part changes with almost every new version of GHC.
This introduces extra work for users of the library who only rely on the stable parts.
They now have to update their upper bounds to accommodate the new major version in order to use a new version of GHC.
Iβm happy to announce the first release of two libraries that expose stable subsets of the template-haskell interface:
template-haskell-lift: a stable home for theLifttypeclasss.template-haskell-quasiquoter: a stable home for theQuasiQuotertype.
These implement GHC Proposal 696.
By replacing a dependency on template-haskell with one or both of these libraries,
users will be more insulated from breaking changes.
These smaller interfaces are much less likely to change going forward. If they do change, we will try to release versions that are compatible with multiple major versions of GHC to ease the transition.
In some cases, these smaller libraries also allow us to backport new features to older versions of GHC.
For instance, GHC-9.16βs template-haskell library will ship with a new defaultQuasiQuoter utility,
but if you use template-haskell-quasiquoter you will be able to benefit from this immediately.
Using template-haskell-liftπ
Suppose you have a module that defines a datatype Foo and you want to add a Lift typeclass instance.
You should add template-haskell-lift to your .cabal fileβs build-depends section and then you can derive a Lift instance like so:
{-# LANGUAGE DeriveLift #-}
module Foo
import Language.Haskell.TH.Lift (Lift)
data Foo = ...
deriving Lift
If you need to write a custom instance, I would recommend using (Typed) Template Haskell splices, rather than using the TemplateHaskell AST types directly from template-haskell.
template-haskell-lift provides compatibility shims for lifting some types that lack appropriate Lift instances.
Using template-haskell-quasiquoterπ
Similarly for QuasiQuoters, users can add template-haskell-quasiquoter to their build-depends and then use it like so:
module FooQuasi
import Foo
import Language.Haskell.TH.QuasiQuoter (QuasiQuoter(..), namedDefaultQuasiQuoter)
import Language.Haskell.TH.Lift (lift)
fooQQ :: QuasiQuoter
fooQQ = namedDefaultQuasiQuoter "fooQQ" {quoteExp = \str -> lift . read @Foo}
Conclusionπ
These libraries should help make it easier to upgrade to a new version of GHC. The more people use them, the greater the benefits will be, so I encourage folks to start using them in their own libraries.
For more information about plans to improve the stability of Template Haskell, take a look at my HEW 2025 talk. For more information about the design of these libraries take a look at GHC Proposal 696.
If you encounter any issues or have suggestions, please open an issue on the respective issue tracker: