我正在编写一个小的 Haskell 编译器,我想尽可能多地实现 Haskell 2010。我的编译器可以解析一个模块,但完成一个程序的模块似乎是一项不平凡的任务。我制作了一些棘手但可能有效的 Haskell 模块示例:
module F(G.x) where
import F as G
x = 2
这里的模块F
export G.x
,但G.x
与 , 相同F.x
,所以当且仅当它 export 时,模块才会F
导出。x
x
module A(a) where
import B(a)
a = 2
module B(a) where
import A(a)
在此示例中,要解析模块的导出,A
编译器必须检查a
导入的来源B
是否与声明的相同a = 2
,但只有在B
导出a
时才会A
导出a
。
module A(f) where
import B(f)
module B(f) where
import A(f)
在解析 module 期间A
,编译器可能假设import f
fromB
存在,这意味着A
export f
,因此B
可以 importA(f)
和 export f
。唯一的问题是在任何地方都没有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 模块?
假设一个模块只包含(简单的)变量绑定,import
s(可能带有as
or qualified
),并导出可能合格的变量和module ...
缩写列表。该算法必须能够:
- 计算每个模块的导出变量的有限列表
- 将每个导出的变量链接到其绑定
- 将每个模块中使用的每个(可能是合格的)变量链接到它的绑定