Haskell: Difference between revisions
m →Using shellFor (multiple packages): formatting |
This flow chart is wrong or at least so much oversimplified that it is actively misleading |
||
(2 intermediate revisions by one other user not shown) | |||
Line 4: | Line 4: | ||
== How to develop with Haskell and Nix == | == How to develop with Haskell and Nix == | ||
{{Note|{{nixos:package|haskellPackages}} is a synonym of <code>haskell.packages.ghcXYZ</code> where <code>XYZ</code> is the current default version of GHC in nixpkgs. However you can use a different version by replacing <code>haskellPackages</code> with the wanted package, for instance use <code>haskell.compiler.ghc884</code> to use GHC 8.8.4. You can get the full list of available GHC versions using: | {{Note|{{nixos:package|haskellPackages}} is a synonym of <code>haskell.packages.ghcXYZ</code> where <code>XYZ</code> is the current default version of GHC in nixpkgs. However you can use a different version by replacing <code>haskellPackages</code> with the wanted package, for instance use <code>haskell.compiler.ghc884</code> to use GHC 8.8.4. You can get the full list of available GHC versions using: | ||
Line 25: | Line 21: | ||
=== Scripting === | === Scripting === | ||
For | For redistributable Haskell scripts on any Nix system, you can use a nix-shell shebang. | ||
<syntaxhighlight lang=haskell> | <syntaxhighlight lang="haskell">#!/usr/bin/env nix-shell | ||
#!/usr/bin/env nix-shell | #! nix-shell --pure -i runghc -p "ghc.withPackages (pkgs: [ pkgs.turtle ])" | ||
#!nix-shell --pure -i runghc -p " | {-# LANGUAGE OverloadedStrings #-} | ||
import Turtle | |||
main = do | main = do | ||
-- do stuff | -- do stuff | ||
echo "Hello world from a distributable Haskell script!"</syntaxhighlight> | |||
</syntaxhighlight> | |||
To remove the additional latency overhead of a nix-shell, add GHC to <code>environment.systemPackages</code> and call <code>runghc</code> in the shebang.<syntaxhighlight lang="nix"> | |||
environment.systemPackages = with pkgs; [ | |||
... | |||
(ghc.withPackages (hsPkgs: with hsPkgs; [ | |||
turtle # Faster startup time with all external shell commands | |||
shh # Piping operators and other goodies | |||
shh-extras # Try shh as an interactive shell | |||
... # ...anything else you want! | |||
]) | |||
]; | |||
</syntaxhighlight>Here's a basic example using the Shh module rather than Turtle, so it can use the pipe operator:<syntaxhighlight lang="haskell"> | |||
#!/usr/bin/env runghc | |||
{-# LANGUAGE TemplateHaskell #-} | |||
{-# LANGUAGE ExtendedDefaultRules #-} | |||
{-# LANGUAGE OverloadedStrings #-} | |||
import Shh | |||
-- $(loadEnv SearchPath) -- Loads entire PATH, may be slow | |||
load SearchPath [ "dd", "sha512sum" ] | |||
To write inline Haskell scripts in nix-code, refer to [[Nix-writers#Haskell]]. | main = do | ||
dd "if=/dev/urandom" "bs=4K" "count=1" |> sha512sum | |||
</syntaxhighlight>To write inline Haskell scripts in nix-code, refer to [[Nix-writers#Haskell]]. | |||
Read [[#Overrides]] if some packages are broken. | Read [[#Overrides]] if some packages are broken. | ||
Line 43: | Line 61: | ||
[https://www.haskell.org/cabal/ Cabal] is the basic Haskell tool used to configure builds and is internally used by all the Haskell's packaging methods (including stack 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: | [https://www.haskell.org/cabal/ Cabal] is the basic Haskell tool used to configure builds and is internally used by all the Haskell's packaging methods (including stack 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: | ||
<syntaxhighlight lang="console"> | <syntaxhighlight lang="console"> | ||
$ nix-shell -p " | $ nix-shell -p "ghc.withPackages (pkgs: [ pkgs.cabal-install ])" | ||
$ cabal init | $ cabal init | ||
… | … | ||
Line 58: | Line 76: | ||
Similarly you can use [https://docs.haskellstack.org/en/stable/ 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): | Similarly you can use [https://docs.haskellstack.org/en/stable/ 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): | ||
<syntaxhighlight lang="console"> | <syntaxhighlight lang="console"> | ||
$ nix-shell -p " | $ nix-shell -p "ghc.withPackages (pkgs: [ pkgs.stack ])" | ||
$ stack new my-project | $ stack new my-project | ||
$ cd my-project | $ cd my-project | ||
Line 84: | Line 102: | ||
You can also use nix in place of stack to keep track of the dependencies in a reproducible way (note that while stack uses a solver to find a working set of dependencies, nix uses a fixed set of packages). Additionally you can benefit from the caching system offered by Nix. To that end, first create a cabal repository (nix also uses cabal internally): | You can also use nix in place of stack to keep track of the dependencies in a reproducible way (note that while stack uses a solver to find a working set of dependencies, nix uses a fixed set of packages). Additionally you can benefit from the caching system offered by Nix. To that end, first create a cabal repository (nix also uses cabal internally): | ||
<syntaxhighlight lang="console"> | <syntaxhighlight lang="console"> | ||
$ nix-shell -p " | $ nix-shell -p "ghc.withPackages (pkgs: [ pkgs.cabal-install ])" --run "cabal init" | ||
… | … | ||
</syntaxhighlight> | </syntaxhighlight> |