code / art / projects

Working With Template Haskell in GHCi

I’ve just started trying to learn and debug Template Haskell and found it a bit rough trying to explore TH interactively, but a couple of things have helped.

First and most obvious, we can use runQ to see the abstract TH syntax which a quasi-quoted expression expands to:

Prelude> :set -XTemplateHaskell
Prelude> :m + Language.Haskell.TH
Prelude Language.Haskell.TH> runQ [| \a -> a+1 |]
LamE [VarP a_1] (InfixE (Just (VarE a_1)) (VarE GHC.Num.+) (Just (LitE (IntegerL 1))))

The second thing that was really helpful to me was turning on the dump- splices debugging option which causes GHC to print the expansions of all $(top-level splices):

Prelude Language.Haskell.TH> :set -ddump-splices 
    Prelude Language.Haskell.TH> :l Zipper.hs
    [1 of 1] Compiling Zipper           ( Zipper.hs, interpreted )
        Zipper.hs:1:0: Splicing declarations
            mkLabelsNoTypes ['Test]
            t1 = lens _t1 (\ b a -> a {_t1 = b})
            t2 = lens _t2 (\ b a -> a {_t2 = b})
        Zipper.hs:1:0: Splicing declarations
            mkLabelsNoTypes ['Zipper]
            lStack = lens stack (\ b a -> a {stack = b})
            focus = lens _focus (\ b a -> a {_focus = b})
    Ok, modules loaded: Zipper.

You can use splices directly in GHCi with the XTemplateHaskell extension turned on (although you get some funny output with -ddump-splices, perhaps related to this):

*Zipper Language.Haskell.TH> let tup = $(tupE $ take 4 $ cycle [ [| "hi" |] , [| 5 |] ])
*Zipper Language.Haskell.TH> tup

That’s all for now! Let me know if you have any tips and I’ll add them here.