Haskell Cabal: «пакет косвенно зависит от нескольких версий одного пакета» - PullRequest
16 голосов
/ 16 февраля 2012

После очистки всех моих cabal install ed-пакетов я запустил следующий сеанс:

$ cabal update
Downloading the latest package list from hackage.haskell.org
james@bast:~/.cabal/packages$ cabal install cabal-dev
Resolving dependencies...
Downloading cabal-dev-0.9.1...
[1 of 1] Compiling Main             ( /tmp/cabal-dev-0.9.124882/cabal-dev-0.9.1/Setup.hs, /tmp/cabal-dev-0.9.124882/cabal-dev-0.9.1/dist/setup/Main.o )
Linking /tmp/cabal-dev-0.9.124882/cabal-dev-0.9.1/dist/setup/setup ...
Configuring cabal-dev-0.9.1...
Warning: This package indirectly depends on multiple versions of the same
package. This is highly likely to cause a compile failure.
package containers-0.4.2.1 requires array-0.4.0.0
package Cabal-1.14.0 requires array-0.4.0.0
package text-0.11.1.13 requires array-0.4.0.0
package deepseq-1.3.0.0 requires array-0.4.0.0
package containers-0.4.2.1 requires array-0.4.0.0
package HTTP-4000.2.2 requires array-0.4.0.0
package cabal-dev-0.9.1 requires containers-0.4.2.1
package Cabal-1.14.0 requires containers-0.4.2.1
package template-haskell-2.7.0.0 requires containers-0.4.2.1
Building cabal-dev-0.9.1...
Preprocessing executable 'ghc-pkg-6_8-compat' for cabal-dev-0.9.1...
<command line>: cannot satisfy -package-id Cabal-1.14.0-4af45d3c8d10dc27db38ae0e7e5a952b: 
    Cabal-1.14.0-4af45d3c8d10dc27db38ae0e7e5a952b is unusable due to missing or recursive dependencies:
      array-0.4.0.0-46f61f5fd9543ebf309552ef84dccc86 containers-0.4.2.1-98f9aa15f9c08b13673dc9d89385f449
    (use -v for more information)
cabal: Error: some packages failed to install:
cabal-dev-0.9.1 failed during the building phase. The exception was:
ExitFailure 1
$ 

Так что причина, по которой я не могу установить cabal-dev, по-видимому, либо в том, что

  • это «косвенно зависит от нескольких версий одного и того же пакета».Тем не менее, cabal не называет пакет, который, по его утверждению, cabal-dev требует нескольких версий.
  • Cabal-1.14.0 имеет "отсутствующие или рекурсивные зависимости", в частности, каким-то образом включающие array-0.4.0.0 и containers-0.4.2.1.

График зависимостей, которые он перечисляет, подтверждает, что ни одно из этих утверждений не является истинным (или что зависимости, которые он перечисляет, являются ложными или неполными):

claimed dependency graph of cabal-dev-0.9.1

Итак: что мне не хватает?Кто или что неправильно: я, cabal, или один или несколько пакетов?

Я работаю:

$ cabal --version
cabal-install version 0.10.2
using version 1.10.1.0 of the Cabal library 
$ ghc --version
The Glorious Glasgow Haskell Compilation System, version 7.4.1
$

1 Ответ

11 голосов
/ 07 июня 2013

Проблема возникает, когда у нас уже установлены пакеты B и C, но они созданы для разных версий D, а затем мы пытаемся использовать оба пакета B и C вместе в пакете A: проблема зависимости от Diamond Это может работать нормально, но только если пакеты Bи C не предоставляют типы, определенные в D, в своих интерфейсах.Если они это сделают, пакет A не сможет использовать функции из B и C вместе, потому что они не будут работать с одним и тем же типом.То есть вы получите ошибку типа.

Чтобы выбрать конкретный пример, предположим, что пакет D является строкой тестирования, и у нас установлены обе версии: bytestring-0.9.0.1 и 0.9.0.4.Допустим, B - это utf8-строка, а C - это регулярное выражение.Допустим, пакет A - это программа-редактор Yi.Итак, дело в том, что в каком-то месте кода в Yi мы хотим передать строку байтов, созданную в результате декодирования UTF-8, в качестве входных данных для одной из функций регулярного выражения.Но это не работает, потому что функции в пакете utf8-string используют тип ByteString из bytestring-0.9.0.1, в то время как функции регулярного выражения в пакете regex используют тип ByteString из bytestring-0.9.0.4.Таким образом, мы получаем ошибку типа, когда пытаемся скомпилировать Yi:

Не удалось найти ожидаемый тип bytestring-0.9.0.4:Data.ByteString.ByteString' against inferred type bytestring-0.9.0.1: Data.ByteString.ByteString '

Насколько GHCзнает, эти два типа совершенно не связаны!

Это явно очень раздражает.Там также нет простого решения.В этом примере мы предполагаем, что пакеты B и C уже были собраны, поэтому на самом деле нет никакого способа разумно использовать два пакета вместе, не перестраивая их для другой версии пакета D. В этом случае очевидным решением являетсявосстановить B, чтобы использовать D-1.1, а не D-1.0.Проблема с перестройкой пакета, конечно, в том, что он ломает все остальные пакеты, которые уже были скомпилированы.Не ясно, что вы хотите, чтобы менеджер пакетов автоматически перестраивал множество явно не связанных пакетов.

В долгосрочной перспективе лучшим решением, по-видимому, было бы то, что делает Nix.В приведенном выше примере вместо замены пакета B, созданного для D-1.0, на B, созданного для D-1.1, Nix добавит еще один экземпляр B, созданный для D-1.1.Таким образом, оригинальный экземпляр B останется неизменным, и ничто не сломается.Это функциональный подход: мы никогда не изменяем значения (установленные пакеты), мы просто создаем новые и собираем старые, когда они больше не нужны.

На практике это означает, что мы должны идентифицировать установленные пакеты, используя некоторый хэшпакет и хэши всех зависимых пакетов.jhc уже делает это, и есть шаги, чтобы сделать нечто подобное для GHC, хотя и нацелены больше на отслеживание изменений API / ABI.Для разумного управления пакетами на основе исходного кода, я думаю, это правильное направление.

Я должен отметить, что это не новая проблема.Вы смогли создать эту проблему с тех пор, как ghc начал разрешать установку нескольких версий одного и того же пакета одновременно.Мы просто замечаем это гораздо чаще, потому что мы разделяем базовый пакет и позволяем обновлять эти разделенные пакеты.

В настоящее время Cabal предупреждает об этой проблеме, но недействительно поможет вам решить это.Для приведенного выше примера мы получили бы:

$ cabal configure
Configuring A-1.0...
Warning: This package indirectly depends on multiple versions of
the same package. This is highly likely to cause a compile failure.
package B-1.0 requires D-1.0
package C-1.0 requires D-1.1
...