查看由模板Haskell生成的代码的首选方法
如您所知,模板Haskell用于在编译时以编程方式生成各种AST拼接。
然而,拼接往往是非常不透明的,而且通常难以辨别拼接实际上产生了什么。 如果你运行Q
monad进行拼接,并且拼接是打好的types的,那么你就可以看到生成的AST片断,但是由于其非结构化的布局,这种表示可能很难理解。
将一段TH生成的AST转换成类似于普通Haskell代码的首选方法是什么?这样代码就可以很容易地被读取和理解了。 能从一个给定的Dec
值重build源代码吗? 是否需要阅读GHC核心代码? 有没有办法来至less构build的AST,使其变得更加可读(除了什么,如pretty-show
包装)?
您可能能够从Language.Haskell.TH.Ppr (使用Language.Haskell.TH自动导入)使用pprint
或ppr
:
GHCi> expr <- runQ [| \fgx -> f (x*2 + 3) . g |] GHCi> putStrLn $ pprint expr \f_0 g_1 x_2 -> f_0 ((x_2 GHC.Num.* 2) GHC.Num.+ 3) GHC.Base.. g_1
这不是很好,但它是有效的哈斯克尔。 您应该能够通过从Prelude名称中去除模块前缀来使输出更好(尽pipe您可能需要小心只去掉预期的前缀;毕竟, Foo.*
是完全有效的中缀运算符)。
你正在寻找编译器的-ddump-splices
标志吗?
作为对ehird答案的补充:
请注意,直接从GHCi直接使用runQ
可能不起作用(例如:使用reify
操作的TH生成器,比较runQ声明之上的注释 )。
当失败的时候,你可以通过pprint
(或者show
),将一个stringexpression式stringE
转换成一个参数putStrLn
:
> putStrLn $(stringE . pprint =<< [| \fgx -> f (x*2 + 3) . g |]) \f_0 g_1 x_2 -> f_0 ((x_2 GHC.Num.* 2) GHC.Num.+ 3) GHC.Base.. g_1