Xop*_*ter 5 haskell module hierarchy
我的理解是,Haskell中模块的虚线语法表示磁盘上的逻辑结构.所以,如果我们有这样的结构:
Main.hs
Foo/
Bar.hs -- exports "Bar"
Quux.hs -- exports "Quux"
Run Code Online (Sandbox Code Playgroud)
...然后在我们的Main.hs
,我们可以做:
import Foo.Bar
import Foo.Quux
Run Code Online (Sandbox Code Playgroud)
(我假设我们只能在文件系统的叶节点上有模块.例如,在上面,我们也无法拥有Foo
模块.)
在这个例子中,我们正在遍历树.如果我们想上去怎么办?
lib/
SomeModule.hs
XYZ.hs
src/
Main.hs
Run Code Online (Sandbox Code Playgroud)
那就是,Main.hs
我们如何进口SomeModule
或XYZ
?
也许这不会是常见现象Main
,但是模块间的依赖关系呢?他们可以合法地需要引用"堂兄"节点.
只需使用模块的完全限定名称,并告诉GHC在哪里可以找到带有该-i
选项的模块层次结构的根.在您的示例中,这意味着您应该使用import XYZ
in Main.hs
来导入模块和命令ghc -i../src --make Main.hs
来编译程序.如果需要编译相互递归的模块,请查看GHC手册的这一部分.
如果您使用Cabal构建程序包,则可以lib
将库中的模块分组,然后使该库成为可执行文件的依赖项.您将具有以下目录结构:
some-package.cabal
lib/
XYZ.hs
src/
Main.hs
Run Code Online (Sandbox Code Playgroud)
该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
...
...
Run Code Online (Sandbox Code Playgroud)
如果您的软件包包含测试或基准测试套件,这将特别有用,因为下面的模块lib
将只编译一次.
这是这种技术的现实例子.