haskell dependencies package cabal cabal-install

Haskell Cabal: “el paquete depende indirectamente de varias versiones del mismo paquete”



dependencies package (1)

El problema surge cuando ya tenemos el paquete B y C instalados pero construidos contra diferentes versiones de D y luego intentamos usar los paquetes B y C juntos en el paquete A: problema de dependencia de Diamond Esto puede funcionar bien, pero solo si los paquetes B y C lo hacen. No exponer los tipos definidos en D en sus interfaces. Si lo hacen, el paquete A no podrá usar las funciones de B y C juntas porque no trabajarán con el mismo tipo. Eso es obtendrá un error de tipo.

Para elegir un ejemplo concreto, supongamos que el paquete D es bytestring y tenemos tanto bytestring-0.9.0.1 como 0.9.0.4 instalados. Digamos que B es utf8-string y C es regex-base. Digamos que el paquete A es el programa editor de Yi. Entonces, el punto es que, en algún lugar del código en Yi, queremos pasar una derivación producida como resultado de la decodificación de UTF-8 como entrada a una de las funciones de expresiones regulares. Pero esto no funciona porque las funciones en el paquete utf8-string están usando el tipo ByteString de bytestring-0.9.0.1 mientras que las funciones regex en el paquete regex están usando el tipo ByteString de bytestring-0.9.0.4. Entonces obtenemos un error de tipo cuando intentamos compilar Yi:

No se pudo hacer coincidir el tipo esperado bytestring-0.9.0.4:Data.ByteString.ByteString'' against inferred type bytestring-0.9.0.1: Data.ByteString.ByteString''

¡Hasta donde sabe GHC, estos dos tipos no tienen ninguna relación!

Esto es obviamente extremadamente molesto. Tampoco hay una solución fácil. En este ejemplo, asumimos que los paquetes B y C ya se han creado, por lo que en realidad no hay manera de usar los dos paquetes juntos sin tener que reconstruirlos contra una versión diferente del paquete D. En este caso, la solución obvia es para reconstruir B para usar el D-1.1 en lugar de D-1.0. El problema con la reconstrucción de un paquete, por supuesto, es que rompe todos los demás paquetes que ya se han creado en su contra. No está claro si desea que un administrador de paquetes vaya a reconstruir automáticamente muchos paquetes aparentemente no relacionados.

A más largo plazo, la mejor solución parece ser hacer lo que hace Nix. En el ejemplo anterior, en lugar de reemplazar el paquete B creado contra D-1.0 con B creado contra D-1.1, Nix agregaría otra instancia de B creada contra D-1.1. Así que la instancia original de B se mantendría sin cambios y nada se rompería. Es el enfoque funcional: nunca mutamos los valores (paquetes instalados) simplemente creamos nuevos y recolectamos basura cuando ya no son necesarios.

En la práctica, significa que tenemos que identificar los paquetes instalados utilizando un hash del paquete y los hashes de todos los paquetes dependientes. jhc ya hace esto y hay movimientos en marcha para hacer algo similar para GHC, aunque está más orientado a rastrear los cambios de API / ABI. Para la gestión de paquetes basada en fuentes sanas, creo que es la dirección correcta a seguir.

Debería tener en cuenta que esto no es un problema nuevo. Has podido construir este problema desde que ghc comenzó a permitir que se instalaran a la vez varias versiones del mismo paquete. Ahora lo estamos notando con mucha más frecuencia porque dividimos el paquete base y permitimos que esos paquetes divididos se actualicen.

El estado actual del juego es que Cabal advierte de este problema, pero en realidad no te ayuda a resolverlo. Para el ejemplo anterior obtendríamos:

$ 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

Después de borrar todos los paquetes de mi cabal install , ejecuté la siguiente sesión:

$ 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 $

Así que la razón por la que no puedo instalar cabal-dev es aparentemente tampoco

  • "depende indirectamente de múltiples versiones del mismo paquete". Sin embargo, cabal no nombra el paquete del que afirma que cabal-dev requiere múltiples versiones de.
  • Cabal-1.14.0 tiene "dependencias faltantes o recursivas", específicamente de alguna manera involucrando array-0.4.0.0 y containers-0.4.2.1 .

Un gráfico de las dependencias que enumera confirma que ninguna de estas afirmaciones es verdadera (o las dependencias que enumera son falsas o incompletas):

Entonces, ¿qué me estoy perdiendo? ¿Quién o qué es incorrecto: yo, cabal o uno o más paquetes?

Estoy corriendo:

$ 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 $