Haskell: Difference between revisions
imported>Yvan-sraka mNo edit summary |
imported>Tobias.bora No edit summary |
||
Line 3: | Line 3: | ||
[https://www.srid.ca/haskell-nix '''Nix recipes for Haskellers'''] aims to get a beginner comfortable managing simple Haskell programs and projects using Nix. | [https://www.srid.ca/haskell-nix '''Nix recipes for Haskellers'''] aims to get a beginner comfortable managing simple Haskell programs and projects using Nix. | ||
== Scripting == | == FAQ and resources == | ||
* [https://discourse.nixos.org/t/haskellpackages-stm-containers-fails-to-build/5416/4?u=srid '''How are Haskell packages managed in nixpkgs?'''] | |||
* [https://www.youtube.com/watch?v=KLhkAEk8I20 '''How to fix broken Haskell packages?''' (video)] | |||
* [https://github.com/mhwombat/nix-for-numbskulls/blob/78bcc186f79931c0e4a1e445e2f6b1f12f6d46be/Haskell/ss-haskell-dev.md Super-Simple Haskell Development with Nix] (and [https://discourse.nixos.org/t/super-simple-haskell-development-with-nix/14287/2 discussion] that provides interesting alternative methods together with there pro and cons) | |||
* [https://discourse.nixos.org/t/nix-haskell-development-2020/6170 Nix Haskell Development (2020)] | |||
== How to develop with Haskell and Nix == | |||
There are multiples ways to develop in Haskell on Nix depending on the simplicity of the project and on whether one want to benefit from the reproducibility offered by nix or not. | |||
=== Scripting === | |||
For simple scripts, you can directly use nix-shell to get a redistributable Haskell script that you can run on any Nix system with `./my-script.hs`: | |||
<pre> | <pre> | ||
#!/usr/bin/env nix-shell | #!/usr/bin/env nix-shell | ||
Line 13: | Line 28: | ||
putStrLn "Hello world from a distributable Haskell script!" | putStrLn "Hello world from a distributable Haskell script!" | ||
</pre> | </pre> | ||
Read below if some packages are broken. | |||
=== Directly using cabal (no nix caching/reproducibility) === | |||
Note that cabal is the basic Haskell tool used to configure builds and is internally used by all the Haskell's packaging methods (including slack and nix). If one does not care about the reproducibility/caching offered by nix, it is always possible to use cabal like in a normal system: | |||
<code> | |||
$ nix-shell -p "haskellPackages.ghcWithPackages (pkgs: with pkgs; [ cabal-install ])" | |||
$ cabal init | |||
… | |||
$ cabal run | |||
Up to date | |||
Hello, Haskell! | |||
</code> | |||
=== Using Stack (no nix caching) === | |||
Similarly you can use stack that let you find the appropriate version of the libraries for you if you do not want the caching offered by nix (stack will build all the dependencies): | |||
<code> | |||
$ nix-shell -p "haskellPackages.ghcWithPackages (pkgs: with pkgs; [ stack ])" | |||
$ stack new my-project | |||
$ cd my-project | |||
$ stack build | |||
$ stack exec my-project-exe | |||
</code> | |||
You can also use the features offered by stack to enable nix integration in order to use nix to install the non-haskell dependencies. You can read more [https://docs.haskellstack.org/en/stable/nix_integration/ here]. | |||
=== Using developPackage === | |||
You can use also nix in place of stack to keep track of the dependencies in a reproducible way. Additionally you can benefit from the caching system offered by Nix. To that end, first create a cabal repository (nix also uses cabal internally): | |||
<code> | |||
$ nix-shell -p "haskellPackages.ghcWithPackages (pkgs: with pkgs; [ cabal-install ])" --run "cabal init" | |||
… | |||
</code> | |||
And create a file <code>default.nix</code> containing: | |||
<syntaxhighlight lang="nix"> | |||
let | |||
pkgs = import <nixpkgs> { }; # pin the channel to ensure reproducibility! | |||
in | |||
pkgs.haskellPackages.developPackage { | |||
root = ./.; | |||
} | |||
<syntaxhighlight> | |||
Then you can build and run the program using: | |||
<code> | |||
$ nix-build | |||
$ ./result/bin/yourprogram | |||
</code> | |||
or run a nix-shell to use the standard development tools provided by cabal: | |||
<code> | |||
$ nix-build | |||
$ ./result/bin/yourprogram | |||
</code> | |||
Nix will automatically read the <code>build-depends</code> field in the <code>*.cabal</code> file to get the name of the dependencies and use the haskell packages provided in the haskell packages configured in nix. Note that some of the packages present in the nix repository are broken (for instance because a package requires an older version of a library while nix only provides a recent version). For this reason it may be necessary to override some packages present in the nix package set. | |||
You can get more details in [https://srid.ca/haskell-nix this tutorial]. | |||
== Overrides == | |||
Since nixpkgs tries to maintain a single Sometimes packages are broken. | |||
== Limitations == | == Limitations == |
Revision as of 20:19, 3 October 2022
Introduction
Nix recipes for Haskellers aims to get a beginner comfortable managing simple Haskell programs and projects using Nix.
FAQ and resources
- Super-Simple Haskell Development with Nix (and discussion that provides interesting alternative methods together with there pro and cons)
How to develop with Haskell and Nix
There are multiples ways to develop in Haskell on Nix depending on the simplicity of the project and on whether one want to benefit from the reproducibility offered by nix or not.
Scripting
For simple scripts, you can directly use nix-shell to get a redistributable Haskell script that you can run on any Nix system with `./my-script.hs`:
#!/usr/bin/env nix-shell #!nix-shell --pure -i runghc -p "haskellPackages.ghcWithPackages (pkgs: [ pkgs.turtle ])" main = do # do stuff putStrLn "Hello world from a distributable Haskell script!"
Read below if some packages are broken.
Directly using cabal (no nix caching/reproducibility)
Note that cabal is the basic Haskell tool used to configure builds and is internally used by all the Haskell's packaging methods (including slack and nix). If one does not care about the reproducibility/caching offered by nix, it is always possible to use cabal like in a normal system:
$ nix-shell -p "haskellPackages.ghcWithPackages (pkgs: with pkgs; [ cabal-install ])"
$ cabal init
…
$ cabal run
Up to date
Hello, Haskell!
Using Stack (no nix caching)
Similarly you can use stack that let you find the appropriate version of the libraries for you if you do not want the caching offered by nix (stack will build all the dependencies):
$ nix-shell -p "haskellPackages.ghcWithPackages (pkgs: with pkgs; [ stack ])"
$ stack new my-project
$ cd my-project
$ stack build
$ stack exec my-project-exe
You can also use the features offered by stack to enable nix integration in order to use nix to install the non-haskell dependencies. You can read more here.
Using developPackage
You can use also nix in place of stack to keep track of the dependencies in a reproducible way. Additionally you can benefit from the caching system offered by Nix. To that end, first create a cabal repository (nix also uses cabal internally):
$ nix-shell -p "haskellPackages.ghcWithPackages (pkgs: with pkgs; [ cabal-install ])" --run "cabal init"
…
And create a file default.nix
containing:
<syntaxhighlight lang="nix">
let
pkgs = import <nixpkgs> { }; # pin the channel to ensure reproducibility!
in pkgs.haskellPackages.developPackage {
root = ./.;
} <syntaxhighlight>
Then you can build and run the program using:
$ nix-build
$ ./result/bin/yourprogram
or run a nix-shell to use the standard development tools provided by cabal:
$ nix-build
$ ./result/bin/yourprogram
Nix will automatically read the build-depends
field in the *.cabal
file to get the name of the dependencies and use the haskell packages provided in the haskell packages configured in nix. Note that some of the packages present in the nix repository are broken (for instance because a package requires an older version of a library while nix only provides a recent version). For this reason it may be necessary to override some packages present in the nix package set.
You can get more details in this tutorial.
Overrides
Since nixpkgs tries to maintain a single Sometimes packages are broken.
Limitations
When using cabal2nix
, Nix does not pull a cabal package by respecting the constraint specified in the cabal file (see example). Issue is discussed here. You should be using `callCabal2nix` anyway.
IFD and Haskell
callCabal2nix
, which is implicitly used for building Haskell projects, uses IFD.[1][2]. This means that since IFD is disabled by default in certain nix commands,[3] the following commands will be broken for Haskell projects whose flake output specifies multiple system attributes:
nix flake show
nix flake check
Haskell.nix
haskell.nix
[4] can automatically translate your Cabal or Stack project and its dependencies into Nix code.