Nice post! The wiki would really benefit from this information.
There are only a few things I would add here:
-
Whenever pinning nixpkgs, I’d recommend adding a comment with the date you used to pin nixpkgs. It is sometimes non-trivial to figure out the date of the channel given just a commit hash, so it is often convenient to know what date a given channel commit corresponds to.
-
In general, you don’t need to do something like the following:
(hself: hsuper: { ghc = hsuper.ghc // { withPackages = hsuper.ghc.withHoogle; }; ghcWithPackages = hself.ghc.withPackages; })
Instead, I’d recommend most people use
shellFor
. It works for projects with multiple packages. You can also passnativeBuildInputs
directly toshellFor
. (ghcid
should technically be innativeBuildInputs
, but in this case it doesn’t really matter.)There is a
withHoogle
argument onshellFor
.(edit: I originally suggested
nativeBuildInput
instead ofnativeBuildInputs
, but that was a mistake. The correct spelling isnativeBuildInputs
(plural).) -
There are a lot of examples of Haskell-related nix code that take
compiler
as a argument, giving the ability to compile with multiple versions of GHC.In practice, I rarely see people actually use this. Since nixpkgs only contains packages in a single stackage version, there are a whole bunch of packages that don’t compile with different compiler versions. I’d recommend taking this out, just to simplify it somewhat. (Of course, this is a very minor nitpick.)
-
Unless you have a good reason, I’d recommend against overwriting the top-level
haskellPackages
attribute in an overlay. Instead, I’d just give it a separate name, likemyHaskellPackages
. Then you can just refer to it asnixpkgs.myHaskellPackages
.This can reduce confusion if you need to get development tools (like
ghcid
) fromhaskellPackages
. Or even if you need to pull in some system library that has a Haskell dependency. -
For package overrides, I’d strongly recommend against using
cabal2nix
to generate Nix expressions on the command line. I consider this an anti-pattern.Instead, you should be using
callHackage
,callHackageDirect
, or justcallCabal2nix
after getting the source withfetchFromGithub
.The only time you should be using
cabal2nix
to generate expressions is when your CI doesn’t allow IFD. Although, in that case, I’d recommend just getting a better CI. -
It is possible to disable tests, haddocks, profiling, etc for all derivations all at once. To do this, you can override
mkDerivation
:myHaskellPackages = super.haskellPackages.override { overrides = hself: hsuper: rec { mkDerivation = args: hsuper.mkDerivation (args // { doCheck = false; doHaddock = false; enableLibraryProfiling = false; enableExecutableProfiling = false; jailbreak = true; }) }; };
This is nice if you are testing things and frequently rebuilding all Haskell packages, but you want everything to build faster.
The big downside of this is that you will no longer be able to get any Haskell packages from the shared nix cache.
-
Link to haskell.nix. Most non-trivial projects are now using
haskell.nix
.haskell.nix
has a couple annoying points, but it seems like it will be the way forward for doing Haskell development using nix.
Also, if you end up adding this info to the Haskell wiki page, you may want to link to it from the Haskell reddit. It seems like there is some interest in Nix from the larger Haskell community.