Ошибка "Ошибка загрузки интерфейса" при загрузке скомпилированных модулей в ghci
Привет, сообщество Haskell,
Я новичок в 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"
Источник для файла 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
и 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 check' ничего не показывает.
Что мне не хватает? Я просмотрел его в стандарте Haskell 2010 (http://www.haskell.org/onlinereport/haskell2010/haskellch5.html), и я не могу найти ошибку. Поэтому мои вопросы:
1) Почему я получаю эту ошибку?
2) Является ли структурирование иерархических модулей такой хорошей практикой? (предполагают значительно большие программы)
Большое спасибо заранее!
Жюль
Ответы
Ответ 1
Изменить: сентябрь 2016 года
Поскольку я первоначально ответил на этот вопрос, растет практика определения модулей Foo.Internal
, которые все еще отображаются. В первоначальном ответе ниже я предложил использовать поле other-modules
. Популярной практикой является определение Foo.Internal.*
модулей, которые отображаются, но явно не являются частью поддерживаемого API. Рациональное для этого шаблона объясняется в ответах на этот вопрос.
Как отмечено в комментариях, в файле .cabal
отсутствует строка other-modules
. Я думаю, cabal install
тогда устанавливает только FoodMod1
, так как это все, о чем было сказано.
Это хороший способ создания внутренних модулей, например, типов, которые используются во всем пакете cabal, который вы не хотите раскрывать в API пакета. Поскольку модули other-modules
не могут быть импортированы извне вашего пакета, это позволяет вам создавать частные функции пакета.