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

jul*_*les 14 haskell module ghc

您好Haskell社区,

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

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

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

FooMod1
|- FooMod1.cabal
|- Setup.hs
|- src
  |- FooMod1.hs
  |- FooMod1
    |- C1.hs
    |- T1.hs
Run Code Online (Sandbox Code Playgroud)

FooMod1.hs的来源:

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

import FooMod1.C1
import FooMod1.T1
Run Code Online (Sandbox Code Playgroud)

C1.hs的来源:

module FooMod1.C1 (
    C1(..)
) where

class C1 a where
    c1FooFun :: a -> IO ()
Run Code Online (Sandbox Code Playgroud)

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"
Run Code Online (Sandbox Code Playgroud)

cabal文件的来源:

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
Run Code Online (Sandbox Code Playgroud)

和Setup.hs:

module Main where

import Distribution.Simple

main = defaultMain
Run Code Online (Sandbox Code Playgroud)

我可以

cabal configure
cabal build
cabal install
Run Code Online (Sandbox Code Playgroud)

没有任何问题.当我开始ghci和

import FooMod1
Run Code Online (Sandbox Code Playgroud)

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

:t c1FooFun
Run Code Online (Sandbox Code Playgroud)

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

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
Run Code Online (Sandbox Code Playgroud)

'ghc-pkg check'什么也没透露.

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

1)为什么我收到此错误?

2)构建像这样的良好实践的分层模块吗?(假设相当大的程序)

提前谢谢了!

儒勒

asm*_*asm 9

编辑:2016年9月

自从我最初回答这个问题以来,人们越来越多地定义Foo.Internal仍然暴露的模块.在下面的原始答案中,我建议使用该other-modules字段.现在流行的做法是定义Foo.Internal.*暴露但明确不属于受支持API的模块.这个模式的理性在这个问题的答案中得到了解释.


如评论中所述,您的.cabal文件缺少该other-modules行.我认为cabal install那时只安装,FoodMod1因为它已被告知.

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