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

17 compiler-construction haskell module mutual-recursion

Haskell支持相互递归的let-bindings,这很棒.Haskell不支持相互递归的模块,这有时很糟糕.我知道GHC有它的.hs-boot机制,但我认为这有点像黑客.

据我所知,对相互递归模块的透明支持应该相对"简单",并且它可以完全像相互递归的let-bindings:不是将每个单独的模块作为编译单元,而是将每个强连接组件模块依赖图作为编译单元.

我在这里错过了什么吗?Haskell以这种方式不支持相互递归模块有什么重要的原因吗?

C. *_*ann 21

这张有6年历史的功能请求票包含了大量的讨论,您可能已经看过了.它的要点是,就GHC而言,它并非完全是一个简单的变化.提出了一些具体问题:

  • GHC目前对编译期间如何处理模块有很多假设,并且显着改变这些假设将大大超过透明支持相互递归模块的好处.

  • 将模块组合在一起意味着必须将它们编译在一起,这意味着需要更多的重新编译和生成单独.hi.o文件的尴尬.

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

  • 您有可能在相互递归的模块组中跨越模块边界的相互递归绑定,这会引发涉及隐式模块级范围(例如默认,可能还有类实例)的任何问题.

  • 当然,还有潜在的未知,未预料到的错误,就像改变GHC长期假设的任何事情一样.即使没有对编译过程进行大量更改,目前也假设许多事情都是基于每个模块进行编译的.

很多人都希望看到这种支持,但到目前为止还没有人能够实现可能的实现,或者制定出一个详细的,明确指定的设计来处理上述类型的所有繁琐的角落案例.

  • @Tinctorius:在这种情况下,你错过了另一个非平凡的原因,特别是负责GHC的人不会认为其他原因是微不足道的.:P (5认同)
  • 如果我忽略技术债务,向后兼容性和已建立的代码(我把它归为"微不足道的原因";)),只剩下一个问题:模块突然变得不那么特殊,这可能会导致类型类出现问题.我已经想到了,但我真的不确定这是不是一个问题.目前是否可以在隐藏实例时导入符号?如果没有,那么模块的SCC无论如何都不能定义/导入冲突的实例,甚至不能用`.hs-boot` ... (3认同)