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:
Zipper.hs:1:0: Splicing declarations
mkLabelsNoTypes ['Test]
======>
Zipper.hs:119:2-25
t1 = lens _t1 (\ b a -> a {_t1 = b})
t2 = lens _t2 (\ b a -> a {_t2 = b})
Zipper.hs:1:0:
Zipper.hs:1:0: Splicing declarations
mkLabelsNoTypes ['Zipper]
======>
Zipper.hs:123:2-27
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
("hi",5,"hi",5)
That’s all for now! Let me know if you have any tips and I’ll add them here.