为什么Haskell不支持互相递归的模块?

18

关于Haskell的相互递归let-bindings和模块

Haskell支持相互递归的let-bindings,这是不错的。但Haskell不支持相互递归的模块,这有时很糟糕。我知道GHC有它的.hs-boot机制,但我认为那有点像一个hack。

据我所知,支持透明的相互递归模块应该相对“简单”,而且它可以像相互递归的let-bindings一样被实现:不是将每个单独的模块作为编译单元,而是将模块依赖图中每个强连通分量作为编译单元。

我是否漏掉了什么?Haskell为什么不以这种方式支持相互递归模块呢?


11
Haskell 支持相互递归的模块,只是 ghc 在实现上做得不太好。 - augustss
1个回答

21

这个6年前的功能请求票包含了相当多的讨论,你可能已经看过了。要点是对于GHC来说,这并不完全是一个简单的变化。有几个特定的问题被提出:

  • GHC目前存在很多关于如何处理编译期间模块的内置假设,而显式支持互递归模块会显著地超过收益。

  • 将一组模块分为一组意味着它们必须一起编译,这意味着更多的重新编译和在生成单独的.hi.o文件时的困难。

  • 与使用hs-boot文件的现有构建的向后兼容性。

  • 可能会发生跨越互递归模块组的互递归绑定,这会引起任何涉及隐式模块级作用域(例如默认和可能是类型类实例)的问题。

  • 当然,在任何改变GHC长期以来的假设的事情中,都有未知、未预料到的错误的潜在风险。即使没有对编译过程进行大规模的更改,目前仍假定许多事情是按模块单独编译的。

很多人都希望支持这一点,但到目前为止,还没有人提出可能的实现或制定出一个处理上述琐碎细节的详细、规范的设计。


3
如果我忽略技术债务、向后兼容性和已经建立的代码(它们被我归为“琐碎原因”中),只有一个问题存在:模块突然不再那么特别了,这可能会对类型类造成问题。我想到过这一点,但我并不确定这是否会成为一个问题。目前是否可以在隐藏实例的同时导入符号?如果不行,那么模块的SCC也不应该能够定义/导入冲突的实例,即使是带有.hs-boot的情况下... - user824425
5
在这种情况下,你错过了另一个非微不足道的原因,特别是 GHC 的负责人认为这些其他原因并不微不足道。:P - C. A. McCann
重新编译确实是一个棘手的问题。因此,当一个人从头开始创建编译器时,就存在两个问题。 - user824425

网页内容由stack overflow 提供, 点击上面的
可以查看英文原文,
原文链接