Не удалось сопоставить тип `binary-0.5.1.1:Data.Binary.Get.Get'с`Get'

Сегодня я собираюсь написать двоичный анализатор 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;
             .... }

Похоже, Getс из Data.Binary а также Data.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.0 а также binary-0.5.1.1так что я незарегистрированный data-binary-ieee754 а также binary-0.7.2.1переустановил data-binary-ieee754, а затем восстановить, кажется, решил проблему!

Вопросы:

У меня еще 2 разных binaryс, но почему это не проблема на этот раз?

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 и типы совпадают снова.
Другие вопросы по тегам