17

在清除了我所有的cabal installed 包后,我运行了以下会话:

$ 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.0and containers-0.4.2.1

它列出的依赖关系图证实了这些声明都不是真的(或者它列出的依赖关系是错误的或不完整的):

声称 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
$
4

1 回答 1

12

当我们已经安装了包 B 和 C 但针对不同版本的 D 构建了包 B 和 C 然后我们尝试在包 A 中同时使用包 B 和 C 时出现问题: Diamond dependency problem 这可以正常工作,但前提是包 B 和 C不要在其接口中公开 D 中定义的类型。如果他们这样做了,那么包 A 将无法同时使用 B 和 C 中的函数,因为它们不会使用相同的类型。那就是你会得到一个类型错误。

举一个具体的例子,假设包 D 是 bytestring 并且我们同时安装了 bytestring-0.9.0.1 和 0.9.0.4。假设 B 是 utf8 字符串,C 是正则表达式。假设包 A 是 Yi 编辑器程序。所以重点是,在 Yi 的代码中的某个地方,我们希望将作为 UTF-8 解码结果生成的字节串作为输入传递给正则表达式函数之一。但这不起作用,因为 utf8-string 包中的函数使用 bytestring-0.9.0.1 中的 ByteString 类型,而 regex 包中的正则表达式函数使用 bytestring-0.9.0.4 中的 ByteString 类型。因此,当我们尝试编译 Yi 时会出现类型错误:

无法匹配预期类型bytestring-0.9.0.4:Data.ByteString.ByteString' against inferred typebytestring-0.9.0.1:Data.ByteString.ByteString'

据GHC所知,这两种类型是完全不相关的!

这显然是非常烦人的。也没有简单的解决方案。在这个例子中,我们假设包 B 和 C 已经被构建,所以实际上没有办法明智地一起使用这两个包而不针对不同版本的包 D 重新构建它们。在这种情况下,明显的解决方案是重建 B 以使用 D-1.1 而不是 D-1.0。重建软件包的问题当然是它破坏了已经针对它构建的所有其他软件包。不清楚您是否希望包管理器自动重建许多明显不相关的包。

从长远来看,最好的解决方案似乎是做 Nix 所做的事情。在上面的示例中,Nix 不会将针对 D-1.0 构建的包 B 替换为针对 D-1.1 构建的 B,而是添加针对 D-1.1 构建的另一个 B 实例。因此 B 的原始实例将保持不变,并且不会中断。这是一种功能性方法:我们从不改变值(已安装的包),我们只是创建新值并在不再需要旧值时进行垃圾收集。

在实践中,这意味着我们必须使用包的一些哈希值和所有依赖包的哈希值来识别已安装的包。jhc 已经这样做了,并且正在为 GHC 做类似的事情,尽管更多地旨在跟踪 API/ABI 更改。对于健全的基于源的包管理,我认为这是正确的方向。

我应该指出,这不是一个新问题。自从 ghc 开始允许一次安装同一个包的多个版本以来,您就已经能够构造这个问题了。我们现在只是更频繁地注意到它,因为我们拆分了基本包并允许升级那些拆分出来的包。

目前的游戏状态是阴谋集团警告这个问题,但并没有真正帮助你解决它。对于上面的例子,我们会得到:

$ 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
于 2013-06-07T19:41:36.147 回答