1

今日は、バイナリSTL ファイルパーサーを作成し、次のコードから始めます。

import Data.Binary.Get
import Data.Word
import Control.Monad
import Data.Bits
import Data.Binary.IEEE754

data Vector3 = Vector3 { x :: Float, y :: Float, z :: Float }

data Triangle = Triangle { normal :: Vector3, 
                           vertex1 :: Vector3, 
                           vertex2 :: Vector3, 
                           vertex3 :: Vector3,
                           attr :: Word16}

getVector3 :: Get Vector3
getVector3 = do
     w1 <- getFloat32le
     w2 <- getFloat32le
     w3 <- getFloat32le
     return $ Vector3 w1 w2 w3    

getTriangle :: Get Triangle
getTriangle = do
     n <- getVector3
     v1 <- getVector3
     v2 <- getVector3
     v3 <- getVector3
     a <- getWord16le
     return $ Triangle n v1 v2 v3 a

stlBinary :: Get ([Triangle])
stlBinary = do
     _ <- getBytes 80 --Ignore the 80 byte header
     cnt <- getWord32be --Read the number of triangles
     replicateM (fromIntegral cnt) getTriangle

GHCコンパイラが不平を言う

Couldn't match type `binary-0.5.1.1:Data.Binary.Get.Get' with `Get'
Expected type: Get Float
  Actual type: binary-0.5.1.1:Data.Binary.Get.Get Float
In a stmt of a 'do' block: w3 <- getFloat32le
In the expression:
  do { w1 <- getFloat32le;
       w2 <- getFloat32le;
       w3 <- getFloat32le;
       return $ Vector3 w1 w2 w3 }
In an equation for `getVector3':
    getVector3
      = do { w1 <- getFloat32le;
             w2 <- getFloat32le;
             w3 <- getFloat32le;
             .... }

Gets fromData.BinaryData.Binary.IEEE754競合しているように見えます。では、これを解決する方法は?

アップデート

私は実際に回避策を持っています - の実装を私のコードに埋め込みましたgetFloat32le(それはわずか6行です)

getFloat32le :: Get Float
getFloat32le = fmap toFloat getWord32le

toFloat :: (Storable word, Storable float) => word -> float
toFloat word = unsafePerformIO $ alloca $ \buf -> do
    poke (castPtr buf) word
    peek buf

これはうまくいきますが、コードを複製するのは楽しくないので、名前の競合の原因を知りたいです。

アップデート

$ghc-pkg list binary
/var/lib/ghc/package.conf.d
   binary-0.5.1.1
/home/joe/.ghc/x86_64-linux-7.6.3/package.conf.d
   binary-0.7.2.0
   binary-0.7.2.1
$ ghc-pkg unregister binary-0.5.1.1
ghc-pkg: unregistering binary-0.5.1.1 would break the following packages: 
bin-package-db-0.0.0.0 ghc-7.6.3 buildwrapper-0.8.6 scion-browser-0.3.1 
hoogle-4.2.32 shake-0.12 buildwrapper-0.8.2 dynamic-cabal-0.3.1 
(use --force to override)
$ ghc-pkg unregister binary-0.7.2.0
ghc-pkg: unregistering binary-0.7.2.0 would break the following packages: 
snap-0.13.2.5 pwstore-fast-2.4.1 SHA-1.6.4 Graphalyze-0.14.1.0 
pandoc-1.12.4.2 zip-archive-0.2.3.1 (use --force to override)
$ ghc-pkg unregister binary-0.7.2.1
ghc-pkg: unregistering binary-0.7.2.1 would break the following packages: 
data-binary-ieee754-0.4.4 (use --force to override)

binary-0.7.2.0andの登録を敢えて解除しなかったbinary-0.5.1.1ので、 and の登録を解除data-binary-ieee754binary-0.7.2.1、再インストールdata-binary-ieee754してから再構築したところ、問題が解決したようです。

質問:

私はまだ 2 つbinaryの異なる を持っていますが、なぜ今回は問題にならないのですか?

4

1 に答える 1

1

あなたは陰謀団の地獄に遭遇しました。次のコマンドを実行した場合:

$ ghc-pkg list binary

複数のバージョンのバイナリがインストールされていることがわかります。問題はData.Binary.IEEE754、プログラムのコンパイルに使用しているバージョンとは異なるバージョンのバイナリに対してコンパイルされることです。また、異なるバージョンのライブラリの型が一致することGetはありません (バイナリ 0.5.1.1 のGet型は、たとえばバイナリ 0.6 の型と一致しません)。

これを修正するにはdata-binary-ieee754、プログラムのコンパイルに使用したバージョンに対して再コンパイルするか、コンパイルに別のバージョンを使用する必要があります (コンパイル-package binary==0.5.1.1時に明示的なフラグを使用)。

ビルドに cabal >= 1.18 を使用する場合は、サンドボックスを使用することもできます。これにより、このような問題を防ぐことができます (完全ではありませんが、ほとんどの場合)。

$ cabal sandbox init         # Create a new sandbox
$ cabal install --only-dep   # Install only dependencies
$ cabal build                # This will now only use the packages in the sandbox and the system packages

http://www.haskell.org/haskellwiki/Cabal/Survivalも参照してください


では、なぜ再インストールしたときに機能したのですdata-binary-ieee754か? 何が起こったかは次のとおりだと思います。

binary-0.5.1.1最初は GHC が付属しているので、 だけをインストールします。今:

  1. data-binary-ieee754に対してビルドされた をインストールしますbinary-0.5.1.1(これが利用可能な唯一のバージョンであるため)。
  2. ここで、新しいバージョンの を必要とする他のパッケージをいくつかインストールしますbinary。=>binary-0.5.1.1とができbinary-0.7.2ました。
  3. ここでプログラムをコンパイルすると、GHC はbinary-0.7.2を選択します。これは、GHC がデフォルトで常にパッケージの最新バージョンを使用することを選択するためです。
  4. を再コンパイルするdata-binary-ieee754と、 に対してコンパイルされるようになりました。これはbinary-0.7.2、利用可能な最新バージョンであるためです => すべてに対してコンパイルされbinary-0.7.2、型が再び一致します。
于 2014-06-21T08:14:36.020 に答える