查看由模板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自动导入)使用pprintppr

 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