How to override a Haskell package in shell.nix

Nix’s support for Haskell is pretty great, but the current state of overriding Haskell packages is a little dicey. See #26561, for example. The Nixpkgs docs tend to focus on writing overlays for the whole system, which doesn’t seem like the right thing to do in most cases. Today I figured out how to override packages in a project-local way, with the help of @MasseR.

When prototyping, I don’t usually bother with packaging an app, so I frequently use haskellPackages.ghcWithPackages to build shells and try things out. So, for example, I wanted to try out scalpel-core. Easy enough;

# shell.nix
with (import <nixpkgs> {});
mkShell {
  buildInputs = [ (haskellPackages.ghcWithPackages (p: [p.scalpel-core])) ];
}

But hm, the latest version (even on unstable) is still 0.5.1, and I’d like to try out 0.6.0. How do I make that change?

The answer, below, ends up being pretty easy to write, although it was hard to discover.

# shell.nix, overriding a Haskell package
with (import <nixpkgs> {});
let
  h = haskellPackages.extend (self: super: {
    scalpel-core = self.callHackage "scalpel-core" "0.6.0" {};
  });
in
mkShell {
  buildInputs = [ (h.ghcWithPackages (p: [p.scalpel-core])) ];
}

What made this hard to discover is ghcWithPackages silently discards any attribute that isn’t a “Haskell package”. Unfortunately, it checks that with {x : x ? isHaskellPackage}, which fails silently for anything that isn’t a set. So, if you don’t follow the types and don’t realize callHackage takes a third argument, ghcWithPackages will silently discard your “package” (which it sees as a partially-applied function) and leave you contemplating different career paths.

I’m adding some documentation to pkgs/development/haskell-modules/make-package-set.nix, so hopefully others will have better luck in the future. :slight_smile:

Also, before you go using haskellPackages.extend yourself, make sure to follow that issue thread I mentioned (#26561). There is some disagreement about using it. (?)

Nonetheless, this solution suits my purpose for now, and I look forward to the continuing evolution of the Haskell ecosystem.

8 Likes

Whoa extend Is news to me. Ive always done my haskell modules as overrides. Game changer.