我的理解是,Haskell 中模块的点语法表示磁盘上的逻辑结构。所以,如果我们有这样的结构:
Main.hs
Foo/
Bar.hs -- exports "Bar"
Quux.hs -- exports "Quux"
...然后在我们的 Main.hs
中,我们可以这样做:
import Foo.Bar
import Foo.Quux
(我假设我们只能在文件系统的叶节点有模块。例如,在上面,我们不可能也有 Foo
模块。)
在这个例子中,我们正在遍历树。如果我们想上升会发生什么?
lib/
SomeModule.hs
XYZ.hs
src/
Main.hs
也就是说,在Main.hs
中,我们如何导入SomeModule
或XYZ
?
也许这在 Main
中并不常见,但是模块间依赖关系又如何呢?他们可能需要引用“表兄弟”节点。
最佳答案
只需使用模块的完全限定名称,并使用 -i
选项告诉 GHC 在哪里找到模块层次结构的根。在您的示例中,这意味着您应该在 Main.hs
中使用 import XYZ
来导入模块和命令 ghc -i../src --make Main.hs
来编译您的程序。如果需要编译相互递归的模块,可以看一下this section GHC 手册。
如果您使用 Cabal 构建软件包,则可以将库中的 lib
下的模块分组,然后使该库成为可执行文件的依赖项。您将拥有以下目录结构:
some-package.cabal
lib/
XYZ.hs
src/
Main.hs
some-package.cabal
文件的相关部分如下所示:
Name: some-package
Version: 1.0
...
Library
...
Exposed-modules: XYZ
Hs-source-dirs: lib
...
Executable some-executable
...
build-depends: some-package == 1.0
...
...
如果您的软件包包含测试或基准测试套件,这尤其有用,因为 lib
下的模块将仅编译一次。
这是a real-life example这种技术。
关于haskell - 指定 "Up The Tree"Haskell 模块,我们在Stack Overflow上找到一个类似的问题: https://stackoverflow.com/questions/19273289/