在 ghci 中加载已编译的模块时出现"无法加载接口"错误



你好,Haskell社区,

我是Haskell的新手,当我试图构建我的第一个更大的项目时遇到了一个问题。

这是这个问题的一个最小的例子(我正在使用阴谋集团来构建)。

这是一个简单模块的目录结构:

FooMod1
|- FooMod1.cabal
|- Setup.hs
|- src
  |- FooMod1.hs
  |- FooMod1
    |- C1.hs
    |- T1.hs

FooMod1.hs:的来源

module FooMod1 (
    C1(..) ,
    T1(..) ,
) where 
import FooMod1.C1
import FooMod1.T1

C1.hs的来源:

module FooMod1.C1 (
    C1(..)
) where
class C1 a where
    c1FooFun :: a -> IO ()

T1.hs的来源:

module FooMod1.T1 (
    T1(..)
) where
import FooMod1.C1
data T1 = T1 deriving(Show)
instance C1 T1 where
    c1FooFun T1 = putStrLn "c1FooFun from T1"

阴谋集团文件的来源:

Name:                      FooMod1
Version:                   0.0.1
Cabal-version:             >=1.10
Build-type:                Simple
library 
  build-depends:           base >= 4 && < 5
  if impl(ghc >= 7.0.0)
     default-language:     Haskell2010
  ghc-options:             -Wall
  exposed-modules:         FooMod1
  ghc-options:             -Wall -rtsopts
  hs-source-dirs:          src, src/FooMod1
  default-language:        Haskell2010

和Setup.hs:

module Main where
import Distribution.Simple
main = defaultMain

我可以做

cabal configure
cabal build
cabal install

没有任何问题。当我启动ghci和时

import FooMod1

它加载模块,我可以看到数据构造函数。但当我试图获得一个函数的类型时,例如

:t c1FooFun

或者构造一个我得到的值:

Failed to load interface for `FooMod1.C1'
There are files missing in the `FooMod1-0.0.1' package,
try running 'ghc-pkg check'.
Use -v to see a list of the files searched for.
In the expression: c1FooFun

"ghc pkg检查"没有显示任何内容。

我错过了什么?我查阅了Haskell 2010标准(http://www.haskell.org/onlinereport/haskell2010/haskellch5.html)我找不到错误。所以我的问题是

1) 为什么我会出现此错误?

2) 构建这样的分层模块是一种好做法吗?(假设程序相当大)

非常感谢!

Jules

编辑:2016年9月

由于我最初回答了这个问题,定义仍然公开的Foo.Internal模块的实践越来越多。在下面的原始答案中,我建议使用other-modules字段。现在流行的一种做法是定义Foo.Internal.*模块,这些模块是公开的,但明确地不是受支持的API的一部分。这个问题的答案解释了这种模式的合理性。


如注释中所述,您的.cabal文件缺少other-modules行。我认为cabal install只安装FoodMod1,因为这就是它被告知的全部内容。

这是一种很好的方法来创建内部模块,例如,在整个cabal包中使用的类型,而您不想在包API中公开这些类型。由于other-modules模块不能从程序包外部导入,因此可以创建程序包专用功能。

最新更新