在Haskell中是否有子模块的概念?

10

我有这段代码

module M where

a = 1
b = 2
x = 10
y = 20

...但是随着模块的增长,处理重复名称变得困难。

是否可能像这样使用命名空间?

module M where
  module A where
    a = 1
    b = 2

  module X where
    x = 10
    y = 20

...然后

...
import M

s = A.a + X.y

module A.B where 有什么问题吗? - Willem Van Onsem
请参阅背包,这是在最前沿的 GHC 中正在进行的工作。 - luqui
1
我有一个模块,其中定义了一些记录,为了避免名称冲突,我想将这些记录分组到子模块中。 - vidi
3个回答

17
据我所知,Haskell目前不支持您提出的内容。但是,这并不妨碍您创建看似有命名空间的模块,例如:
module Top where

myTopFunc :: a -> Int
myTopFunc _ = 1

另一个文件中:

module Top.Sub where

mySubFunc :: a -> String
mySubFunc _ = "Haskell"

除此之外,您还有更多的技巧来安排您的模块。如果您将模块A导入B,则可以将A的可见实体从B中导出,就好像它们是自己的一样。随后,在导入B时,您将能够使用那些函数/数据类型等,而不知道它们最初来自哪里。使用上面的模块作为示例:

module Top (
  myTopFunc,
  TS.mySubFunc
  ) where

import qualified Top.Sub as TS

myTopFunc :: a -> Int
myTopFunc _ = 1

现在,您只需要导入Top,就可以使用这两个函数了。
import Top (myTopFunc, mySubFunc)

1
第二个例子是我能想到的最接近原始伪Haskell的翻译。M 变成 M.Core 或类似的形式,A/B 变成 M.A/M.B,而新模块 M 则简单地重新导出所有定义。 - user2407038

5

有层级的模块名称。你可以拥有名为MM.AM.X的模块,但是模块本身并不嵌套,而且在语言上MM.A没有关联。

如果你希望M导出M.AM.X导出的所有内容,你必须明确指定:

module M (module M.A, module M.X) where
import M.A
import M.X
-- rest of M

2
不,你不能。但是你的评论提到你只是想避免命名冲突。为此,你可以使用 {-# LANGUAGE DuplicateRecordFields #-} 扩展,编译器将允许重复的记录字段名。

我知道这个扩展,但如果我使用makeLenses为我的记录生成Lens,则它无法工作。 - vidi
@vidi 是的,当我偶然发现这个问题并找到你的提问时,我也在寻找同样的解决方案。但事实上,这个功能相当有限。看起来 PureScript 对常规记录类型的支持要好得多;作为一个新手正在实现 Web 服务的 Haskell 用户,我想我可能需要更深入地研究一下 PureScript。 - Dax Fohl

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