【问题标题】:Resolving edge-case Haskell module imports and exports解决极端情况 Haskell 模块导入和导出
【发布时间】:2012-12-14 22:09:39
【问题描述】:

我正在编写一个小的 Haskell 编译器,并且我希望尽可能多地实现 Haskell 2010。我的编译器可以解析一个模块,但完成一个程序的模块似乎是一项不平凡的任务。我编造了一些棘手但可能有效的 Haskell 模块示例:

module F(G.x) where
  import F as G
  x = 2

这里模块F导出G.x,但G.xF.x相同,所以模块F导出x当且仅当它导出x

module A(a) where
  import B(a)
  a = 2

module B(a) where
  import A(a)

在这个例子中,为了解析模块A的导出,编译器必须检查从B导入的a是否与声明的a = 2相同,但B导出a如果,且仅当 A 导出 a

module A(f) where
  import B(f)

module B(f) where
  import A(f)

在解析模块A期间,编译器可能假设存在从B导入的f,这意味着A导出f,因此B可以导入A(f)和导出@987654346 @。唯一的问题是在任何地方都没有定义f :)。

module A(module X) where
  import A as X
  import B as X
  import C as X
  a = 2

module B(module C, C.b) where
  import C
  b = 3

module C(module C)
  import B as C
  c = 4

这里,module 导出导致导出列表相互依赖并依赖于它们自身。

所有这些示例都应该是有效的 Haskell,如 Haskell 2010 规范所定义。

我想问一下有没有什么想法可以正确完整的实现 Haskell 模块?

假设一个模块只包含(简单)变量绑定,imports(可能带有asqualified),并导出可能合格的变量列表和module ... 缩写。该算法必须能够:

  • 计算每个模块的导出变量的有限列表
  • 将每个导出的变量链接到其绑定
  • 将每个模块中使用的每个(可能是合格的)变量链接到其绑定

【问题讨论】:

    标签: haskell compiler-construction compilation


    【解决方案1】:

    你可能对A Formal Specification for the Haskell 98 Module System感兴趣。

    我还在一系列博客文章中介绍了一些有趣的边缘案例,目前仅发布了first one

    最后,我正在研究那个——一个处理 Haskell 模块的库。它叫做haskell-names

    根据您的目标,您可以简单地在编译器中使用它、研究源代码或做出贡献。 (您的示例将成为出色的测试用例。)


    回答你的问题:递归模块是通过计算一个固定点来处理的。

    您从模块图中的强连接组件开始。对于此组件中的每个模块,您首先假设它不导出任何内容。然后您重新访问这些模块,并根据新信息计算新的导出列表。你可以证明这个过程是单调的——每次导出列表增长(或者,至少不缩小)。迟早它会停止增长——然后你就到达了固定点。

    你可以通过借鉴静态分析的一些想法来优化这个算法(那个社区非常擅长计算不动点),但我的包目前实现了朴素算法(code)。

    【讨论】:

    • 哇,谢谢,我什至不希望有针对这个问题的论文和图书馆 :)
    猜你喜欢
    • 1970-01-01
    • 1970-01-01
    • 1970-01-01
    • 1970-01-01
    • 1970-01-01
    • 2011-07-25
    • 1970-01-01
    • 1970-01-01
    • 1970-01-01
    相关资源
    最近更新 更多