查看 Template Haskell 生成的代码的首选方法
如您所知,Template Haskell 用于在编译时以编程方式生成各种 AST 拼接。
然而,拼接通常非常不透明,并且通常很难辨别拼接实际生成的内容。如果您为拼接运行Q
monad,并且该拼接是正确类型的,您将获得生成的 AST 片段的可显示
表示,但该表示可以是由于其非结构化布局,非常难以理解。
将 TH 生成的 AST 转换为类似于普通 Haskell 代码的首选方法是什么,以便代码可以轻松阅读和理解?可以根据给定的 Dec
值重建源代码吗?是否必须阅读 GHC 核心代码?有没有一种方法至少可以构建 AST,使其变得更具可读性(超出 pretty-show
包的作用)?
As you know, Template Haskell is used to generate various kinds of AST splices programmatically at compile-time.
However, a splice can often be very opaque, and it is often difficult to discern what a splice actually generates. If you run the Q
monad for a splice, and the splice is well-typed, you get a show
able representation of the generated piece of AST, but this representation can be very difficult to understand, because of its unstructured layout.
What is the preferred method for converting a piece of TH-generated AST into something akin to normal Haskell code, so that the code can be easily read and understood? Can one reconstruct source code from e.g. a given Dec
value? Does one have to read the GHC Core code? Is there a way to at least structure the AST so that it becomes more readable (Beyond what e.g. the pretty-show
package does)?
如果你对这篇内容有疑问,欢迎到本站社区发帖提问 参与讨论,获取更多帮助,或者扫码二维码加入 Web 技术交流群。
绑定邮箱获取回复消息
由于您还没有绑定你的真实邮箱,如果其他用户或者作者回复了您的评论,将不能在第一时间通知您!
发布评论
评论(3)
您是否正在寻找编译器的
-ddump-splices
标志?Are you looking for the
-ddump-splices
flag to the compiler?您可以使用 Language.Haskell.TH.Ppr (使用 Language.Haskell.TH ):
它并不漂亮,但它是有效的Haskell。您应该能够通过从 Prelude 名称中剥离模块前缀来使输出更好(尽管您可能需要小心地仅剥离预期的前缀;
Foo.*
是一个完全有效的中缀运算符,之后全部)。You may be able to use
pprint
orppr
from Language.Haskell.TH.Ppr (imported automatically with Language.Haskell.TH):It's not pretty, but it is valid Haskell. You should be able to make the output nicer by stripping off module prefixes from Prelude names (although you might need to be careful to only strip the expected prefix;
Foo.*
is a perfectly valid infix operator, after all).作为对第三个答案的补充:
请注意,直接从 GHCi 使用
runQ
一般来说可能行不通
(例如:使用
reify
操作的TH生成器,参见上述评论runQ 声明)。
当失败时,您可以
pprint
(或show
),转换引入字符串表达式stringE
,然后作为参数拼接到putStrLn< /代码>:
As a complement to ehird answer:
Note that using
runQ
directly from GHCiin general might not work
(e.g.: TH generators that use
reify
operations,cf. comments above the runQ declaration).
When that fails, you can
pprint
(orshow
), transform intro a string expressionstringE
then splice as an argument toputStrLn
: