haskellのstackを利用時に一部のパッケージをimportし、そのままstack buildするとエラーとなりbuildに失敗することがあります。
前回投稿した記事
haskellのstackでghc-modを利用時に一部パッケージのimportでエラーとなる
に似た内容となっていますが
前回とはエラー発見のアプローチが違うということと、
前回までstack、haskellのpackageについてちゃんと理解していなかったということでお許しを。
ベース
今回プロジェクト名をmyappとしています。
module Main where
main :: IO ()
main = print "Hello, World"
以上でstack buildし実行すると、
"Hello, World"
と表示されます。
エラーとなる例
「すごいHaskellたのしく学ぼう」の中でも紹介されているモジュールから。
module Main where
import Data.List
import System.IO
import Control.Exception
import System.Directory
import System.Random
import Control.Monad.Writer
main :: IO ()
main = print "Hello, World"
のように6種類のモジュールをimportしてstack buildすると、
/dev/haskell/myapp/app/Main.hs:6:1: error:
    Failed to load interface for ‘System.Directory’
    It is a member of the hidden package ‘directory-1.2.6.2’.
    Perhaps you need to add ‘directory’ to the build-depends in your .cabal file.
    Use -v to see a list of the files searched for.
/dev/haskell/myapp/app/Main.hs:7:1: error:
    Failed to load interface for ‘System.Random’
    Use -v to see a list of the files searched for.
/dev/haskell/myapp/app/Main.hs:8:1: error:
    Failed to load interface for ‘Control.Monad.Writer’
    Perhaps you meant
      Control.Monad.Fail (from base-4.9.0.0)
      Control.Monad.Fix (from base-4.9.0.0)
      Control.Monad.Zip (from base-4.9.0.0)
    Use -v to see a list of the files searched for
のようなエラーが表示されました。
import System.Directory
import System.Random
import Control.Monad.Writer
の部分がエラーとなっているみたいです。
原因
stackではmyapp.cabalの中で利用するパッケージを明記してやる必要があります。デフォルトでは、
executable myapp-exe
  hs-source-dirs:      app
  main-is:             Main.hs
  ghc-options:         -threaded -rtsopts -with-rtsopts=-N
  build-depends:       base
                     , myapp
  default-language:    Haskell2010
のように、baseとmyappパッケージだけが明記されています。(myappは自分のプロジェクト)
よって、このままではbaseに含まれるモジュールしか利用することができません。
baseパッケージには以下のモジュールが含まれています。
https://hackage.haskell.org/package/base
よって、baseパッケージに含まれていなかった、
import System.Directory
import System.Random
import Control.Monad.Writer
が失敗したというわけです。
解決策
よって、解決策としてはmyapp.cabalに利用するパッケージを明記すればいいだけです。
先程のエラーを解決してみましょう。
System.Directory,System.Random,Control.Monad.Writerはそれぞれ、
directory, random, mtlパッケージに属しているので、
executable myapp-exe
  hs-source-dirs:      app
  main-is:             Main.hs
  ghc-options:         -threaded -rtsopts -with-rtsopts=-N
  build-depends:       base
                     , myapp
+                    , directory
+                    , random
+                    , mtl
  default-language:    Haskell2010
のように変更してやれば解決します。
src以下、test以下 のファイルで同じエラーが発生する
上記の解決策ではapp以下でのimportのエラーしか解決できません。
src以下、test以下で同じように怒られるので、
src以下
library
  hs-source-dirs:      src
  exposed-modules:     Lib
  build-depends:       base >= 4.7 && < 5
  default-language:    Haskell2010
test以下
test-suite myapp-test
  type:                exitcode-stdio-1.0
  hs-source-dirs:      test
  main-is:             Spec.hs
  build-depends:       base
                     , myapp
  ghc-options:         -threaded -rtsopts -with-rtsopts=-N
  default-language:    Haskell2010
をappの時と同じようにbuild-dependsに必要なパッケージを追記してやれば解決します。
