Не удалось сопоставить тип `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. Сейчас:
- Вы устанавливаете
data-binary-ieee754
, который построен противbinary-0.5.1.1
(потому что это единственная доступная версия). - Теперь вы устанавливаете некоторые другие пакеты, для которых требуется более новая версия
binary
, => Теперь у вас естьbinary-0.5.1.1
а такжеbinary-0.7.2
, - Когда вы сейчас компилируете программу, GHC выбирает
binary-0.7.2
потому что GHC по умолчанию всегда выбирает использовать последнюю версию любого пакета. - Когда вы перекомпилируете
data-binary-ieee754
, теперь он составлен противbinary-0.7.2
потому что это теперь последняя доступная версия => все скомпилированоbinary-0.7.2
и типы совпадают снова.