program instalar haskell cabal

haskell - program - instalar cabal



¿Cómo reducir la duplicación en los campos dependientes de la compilación de un archivo.cabal? (4)

Aquí hay un archivo .cabal:

Name: myprogram Version: 0.1 -- blah blah blah Cabal-version: >=1.9.2 Executable myprogram HS-source-dirs: src Main-is: Main.hs Build-depends: attoparsec == 0.10.*, base == 4.3.*, -- long long list of packages Test-Suite test HS-source-dirs: test, src Type: exitcode-stdio-1.0 Main-is: Main.hs Build-depends: attoparsec == 0.10.*, base == 4.3.*, -- long long list of packages QuickCheck == 2.4.*

¿Hay alguna manera de que pueda reemplazar la larga lista de paquetes dependientes de la compilación para el conjunto de pruebas con "lo mismo que para el ejecutable, más QuickCheck"?

Editar: información de la versión.

  • cabal-dev 0.9
  • cabal-install 0.10.2
  • Librería de Cabal 1.10.2.0
  • GHC 7.0.4
  • Plataforma Haskell 2011.4.0.0

¿Hay alguna manera de que pueda reemplazar la larga lista de paquetes dependientes de la compilación para el conjunto de pruebas con "lo mismo que para el ejecutable, más QuickCheck"?

No que yo sepa. Sin embargo, hay una forma de mencionar solo la lista de paquetes de acuerdo con la build-depends una vez, estructurando su proyecto en tres objetivos:

  1. una biblioteca que contiene todo su código y necesita la larga lista de dependencias de compilación.
  2. un archivo ejecutable que consta de un solo archivo y depende de la base y la biblioteca desde arriba.
  3. un conjunto de pruebas que depende de la biblioteca desde arriba y de los paquetes de prueba que está utilizando.

Tal vez este enfoque es lo que la respuesta de Indygemma propone, pero el archivo Cabal propuesto no lo logrará del todo, como señala Norman Ramsey en un comentario. Estos son los puntos principales de lo que necesita en un archivo Cabal. Para ver un ejemplo completo que funciona para mí, puedes mirar este archivo Cabal .

name: my-program version: ... library hs-source-dirs: src-lib build-depends: base, containers, ... exposed-modules: My.Program.Main, ... executable my-program hs-source-dirs: src-exec main-is: my-program.hs Build-depends: base, my-program test-suite tests type: exitcode-stdio-1.0 hs-source-dirs: src-test main-is: tests.hs other-modules: ... build-depends: base, my-program, test-framework, ...

Puntos importantes:

  • Hay tres directorios de origen separados para los tres objetivos. Esto es necesario para evitar que GHC vuelva a compilar los archivos de la biblioteca al construir los otros objetivos.

  • Todo el código de la aplicación está en la biblioteca. El ejecutable es solo un contenedor, como este:

    import My.Program.Main (realMain) main = realMain

  • La biblioteca expone todos los módulos que son necesarios para la prueba.

El último punto destaca el inconveniente de este enfoque: termina teniendo que exponer los módulos internos. El principal beneficio de este enfoque es que tiene menos duplicación en el archivo Cabal y, quizás más importante, menos duplicación en el proceso de compilación: el código de la biblioteca se compilará solo una vez y luego se vinculará con el ejecutable y el conjunto de pruebas. .


Hay una sección de biblioteca opcional para archivos .cabal, que resuelve su problema.

name: myprogram version: 0.1 -- blah blah blah cabal-version: >=1.9.2 library build-depends: attoparsec == 0.10.* , base == 4.3.* -- long long list of packages executable myprogram hs-source-dirs: src main-is: Main.hs test-suite test hs-source-dirs: test, src type: exitcode-stdio-1.0 main-is: Main.hs build-depends: QuickCheck == 2.4.*


No es una manera fácil:

  • puedes usar m4 y especificar tus dependencias una vez, pero luego necesitarás volver a procesar tu archivo Cabal a través de m4 cada vez que lo cambies.

  • puede mover el código que está probando a una biblioteca, y luego especificar la biblioteca en su Build-depends para la prueba. Eso requiere que instale una biblioteca incluso para ejecutar la prueba.

  • Simplemente no puedes poner la prueba en el archivo cabal. Compilarlo con ghc --make, que generará dependencias. Pero luego pierdes la integración cabal.


También podría considerar usar hpack lugar de escribir el archivo .cabal a mano:

En el formato package.yaml de hpack, puede especificar un campo de dependencies común cuyas entradas se agreguen al campo de dependencies de cada componente al generar el archivo .cabal.

Por ejemplo, vea el propio package.yaml hpack.cabal y el hpack.cabal generado.

Para comenzar a usar hpack con un paquete existente, puede usar hpack-convert que generará el paquete.yaml de un archivo existente .cabal.

Para crear un nuevo paquete que use hpack, puede usar la plantilla simple-hpack la pila de la simple-hpack manera: stack new mypkg simple-hpack .

Si usa stack para el desarrollo, no tiene que llamar a hpack manualmente para regenerar el archivo .cabal desde un paquete actualizado.yaml - stack lo hará automáticamente.