Good day!
PhD student here, I have been working with Template Haskell (TH) to generate specialised code and observe potential speed-ups at runtime.
After 3 small-to-medium sized projects/experiments, I found it quite boring to build TH ASTs manually, and the code base ended quite cluttered and unpleasant to read (might be a skill issue though).
For a side project, I played around with lenses and the State monads, which when mixed together, allow interacting this the state object in an imperative way (e.g. see operators like (+=)).
So with a bit of code generation, I came up with template-haskell-natural, a DSL that allows building TH ASTs through monadic operations. The library is named that way because writing the meta-program feels natural.
For example, a code generator that outputs the the identity function (along with its type signature) could look like this:
import qualified Language.Haskell.TH.Natural.Syntax.Builder as B
genId :: DecsQ
genId = genDecs $ newFun "myId" $ B.do
-- Optional
setSignature $ newSignature $ B.do
a <- liftB $ newTypeVar "a"
addParam a
setReturnType r
bodyFromExpr $ newExpr $ B.do
a <- arg
returns a
This particular example may feel a bit verbose, but you can find more byte-sized examples in this blog article.
TLDR, the library allows:
- Building ASTs for type classes, instances, data types and function declarations
- Building ASTs for lambda and do expressions
- Including pattern matching and deconstruction
- (Limited) support for typed expressions
Internally, the library generates standalone constructors and lenses for each field. It also provides a wrapper layer (Builder) to ensure (to a certain extent) that the AST to produce is somewhat valid (e.g. that the last statement in a do expression is not a bind).
From the consensus I could read online about Template Haskell, it’s usually avoided/disliked because of it’s unstable API and how it impacts the compilation process.
But I would be curious to see what Template Haskell users think of this approach. Feedback would be appreciated ![]()
Thank you!