“无法加载接口”在ghci中加载编译的模块

问题描述:

你好哈斯克尔社区,“无法加载接口”在ghci中加载编译的模块

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

这是问题的最小例子(我正在使用cabal来构建)。

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

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)正在构建一个类似于良好实践的分层模块吗? (假设相当大的程序)

非常感谢提前!

+3

我想你的cabal文件丢失了'other-modules:'行。你只告诉它关于'FooMod1'模块。我不知道为什么这不是编译错误。 – asm

+0

@ Andrew:非常感谢您这是问题所在......您是否可以将解决方案转贴为答案,以便我可以接受它? – jules

编辑:2016年9月

因为我本来回答了这个问题有定义Foo.Internal模块仍然面临的越来越多的做法。在下面的原始答案中,我建议使用other-modules字段。目前流行的一种做法是定义Foo.Internal.*模块,这些模块已公开但显式不属于受支持的API。在this question的回答中解释了这种模式的合理性。


正如评论中的.cabal文件丢失other-modules行指出。我认为cabal install然后只安装FoodMod1,因为这是所有它被告知。

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