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 theLift
typeclasss.template-haskell-quasiquoter
: a stable home for theQuasiQuoter
type.
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 QuasiQuoter
s, 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: