2015年11月8日日曜日

[haskell][stack] stack exec ghciで”Couldn't match expected type"エラーが発生する問題の対処

先日、haskellのパッケージ管理をcabalからstackに移行して「便利〜!」と感動していたところなのですが、stach exec ghciでソースをロードしようとすると"Couldn't match expected type: xxxxx"とエラーが発生する問題に遭遇しました。
ネットの情報を参考に解決することができたのでその手順をまとめておきます。

問題:

stack buildは成功するにもかかわらず、stack exec ghci xxx.hs(xxx.hsはbuild対象のファイル)がエラーになる。
stack exec ghci実行時のエラーログ:
% stack exec ghci FileToVec.hs
GHCi, version 7.10.2: http://www.haskell.org/ghc/  :? for help
[1 of 1] Compiling FileToVec        ( FileToVec.hs, interpreted )

FileToVec.hs:42:18:
    Couldn't match expected type ‘V.Vector a’
                with actual type ‘vector-0.10.12.3:Data.Vector.Vector a0’
    NB: ‘V.Vector’
          is defined in ‘Data.Vector’ in package ‘vector-0.11.0.0’
        ‘vector-0.10.12.3:Data.Vector.Vector’
          is defined in ‘Data.Vector’ in package ‘vector-0.10.12.3’
    Relevant bindings include
      v :: vector-0.10.12.3:Data.Vector.Vector a0
        (bound at FileToVec.hs:40:15)
      file_to_vec :: FilePath -> IO (V.Vector a)
        (bound at FileToVec.hs:33:1)
    In the first argument of ‘return’, namely ‘v’
    In a stmt of a 'do' block: return v
Failed, modules loaded: none.
Leaving GHCi.
この環境でのstack buildは以下のようなログで成功しています。
% stack build
csv2db-0.1.0.0: build
Preprocessing executable 'csv2db' for csv2db-0.1.0.0...
[2 of 4] Compiling FileToVec        ( FileToVec.hs, .stack-work/dist/x86_64-osx/Cabal-1.22.4.0/build/csv2db/csv2db-tmp/FileToVec.o )
[3 of 4] Compiling DbRecord         ( DbRecord.hs, .stack-work/dist/x86_64-osx/Cabal-1.22.4.0/build/csv2db/csv2db-tmp/DbRecord.o ) [TH]
Linking .stack-work/dist/x86_64-osx/Cabal-1.22.4.0/build/csv2db/csv2db ...
    DbRecord
    FileToVec
    MyArgs
csv2db-0.1.0.0: install
Installing executable(s) in XXXX

解決方法:

以下の2つの方法があります。
  1. execコマンドを用いず、stack ghciで起動する
  2. execコマンドを利用しなければロードすることができます。普通はこちらの手順を実行するのが正しいはずです。が、ファイル指定で起動できないのでプロンプトから:loadコマンドを実行する必要があります。
    % stack ghci
    Using main module: Package `csv2db' component exe:csv2db with main-is file: /Users/kurokawa/git/work_haskell/csv2db/Main.hs
    Configuring GHCi with the following packages: csv2db
    GHCi, version 7.10.2: http://www.haskell.org/ghc/  :? for help
    [1 of 4] Compiling FileToVec        ( FileToVec.hs, interpreted )
    [2 of 4] Compiling MyArgs           ( MyArgs.hs, interpreted )
    [3 of 4] Compiling DbRecord         ( DbRecord.hs, interpreted )
    [4 of 4] Compiling Main             ( XXXX/Main.hs, interpreted )
    Ok, modules loaded: MyArgs, DbRecord, Main, FileToVec.
    *Main> :load FileToVec
    [1 of 1] Compiling FileToVec        ( FileToVec.hs, interpreted )
    Ok, modules loaded: FileToVec.
    *FileToVec>
    
    stack ghci実行時にソースファイルを引数で指定した場合、以下のようなエラーになるのでご注意を。
    % stack ghci FileToVec.hs
    Error parsing targets: Directory not found: FileToVec.hs
    
  3. cabalを直実行して必要パッケージをインストールする
  4. stackを利用しないでcabal installで依存パッケージをインストールし、ローカルのxxx.hsがコンパイルできる状態にし、stackを利用しないでcabal exec ghci xxx.hsを実行する。成功時のログ:
    % cabal install vector
     ... snip...
    % cabal exec ghci FileToVec.hs
    GHCi, version 7.10.2: http://www.haskell.org/ghc/  :? for help
    [1 of 1] Compiling FileToVec        ( FileToVec.hs, interpreted )
    Ok, modules loaded: FileToVec.
    *FileToVec>
    

エラー原因(の推測):

stack build実行時に起動されるcabalが参照するパッケージリストと、stack exec ghciで起動されるghciが参照するパッケージリストが、異なっているのが原因だと思われます。
stack build実行時には、stackが内部で管理している(?)パッケージリストを参照しているようですが、stack exec ghciで起動されたghciはcabalを直接起動したときに参照されるパッケージリストを参照し、バージョンのズレが生じてエラーになります。

参考:

0 件のコメント:

コメントを投稿