I would like bring some clarity to the state of the Nix Haskell ecosystem and to discuss how we can make it better by making it simpler, reduce maintenance burden and joining efforts. Looking at https://discourse.nixos.org/t/nix-haskell-development-2020/6170/2?u=malteneuss there seem to be at least two large competing Nixifying approches:
-
Nixpkgs approach. Current “official” Nixpkgs
haskellPackages
(formerly haskell4nix)
with some serious limitations:
-
Uses a
cabal2nix
Nix library, which parses but ignores the<package>.cabal
packages version constraints and uses whatever package set versions that happen to be selected within Nix. This means that what is build outside of Nix withcabal build
and what is build within Nix can be quite different. -
Only one blessed stable package set, namely
haskellPackages
, for a fixed GHC compiler version (currently GHC 9.6). When i wanted to use a newer GHC version like 9.10 and newer packages sets likehaskell.packages.ghc910
, builds failed all over the place, which requires a lot manual work to fix, which as i understood is one reason for only one blessed package set. Basically, just enough Haskell support to package and provide single Haskell apps. -
Doesn’t support
cabal.project
files for monorepo projects out of the box. At least i could find anything, so i had to use tools built on top like https://github.com/srid/haskell-flake/. -
Probably no cross-compilation support (at least i haven’t found anything).
The main benefit for this approach is that it doesn’t use import-from-derivation (IFD), which is forbidden in Nixpkgs. Also short build times as the NixOS cache usually has all packages.
- IOHK “haskell.nix” approach. Independently developed Haskell Nix setup with other but smaller limitations:
-
Lives out-of-Nixpkgs-tree. Likely receives less attentation and community support than possible.
-
Often long build times. When i tried it, required several GHC versions under the hood, not all of which were cached. Documentation on what is cached and not, seems to be out-of-date.
-
Quite different Nix setup and Nix values to use.
-
Uses import-from-derivation.
-
Support comes mainly from a single company in the volatile crypto industry.
The big upsides are
-
Supports lots of GHC versions and arbitrary package sets, whatever is defined a
<package>.cabal
file. -
Is developed and tested within industrial use.
-
First-class support for cross-compilation. Quit important for GHCjs, WASM and RISCV in the future.
-
Just works, at least in a few of my test setups.
-
Maintenance burden seems to be less, although i don’t know if this comes from the IFD setup or the project members just do the manual work more eagerly.
To me it seems that the haskell.nix approach is the way to go as @cdepillabout sometimes mentioned. It seems to work better out of the box, scales (works with whatever Haskell setup you start with), and seems to reduce the maintenance burden.
Can we allow IFD in Nixpkgs and make it the official way to Nixify Haskell code? If not and it has to live
out-of-tree, can we officially endorse it the Nixpkgs Haskell docs?
If both aren’t possible, can we push the Haskell tools to change? It seems that Rust with it’s cargo.lock
file doesn’t need IFD and has a good official Nixpkgs Rust setup. If the deterministic lock file is the important part, maybe we can get Haskell developers to adopt this better (i know there’s some Cabal freeze file, but i have almost never seen it).
What do you think? (Also please correct me where i’m mistaken)