How to use a more recent GHC?

When I run cabal repl, by default I get GHC version 8.10.7. I’d like to try 9.2.0. (I can also see ghc-8.10.4 in ~/.cabal/store, but I don’t know how it got there.)

My config, in relevant part

My current configuration includes these packages:

haskellPackages.Cabal_3_6_2_0
cabal-install
ghc

Maybe some of those are redundant, I don’t know.

What I’ve tried

I’ve tried putting this in a project’s cabal.project file:

with-compiler: ghc-9.2.1

When I do, I get this error:

cabal: Cannot find the program 'ghc'. User-specified path 'ghc-9.2.1' does not
refer to an executable and the program is not on the system path.

I’ve also tried adding either of the GHC-9.2 packages on https://search.nixos.org/packages to the package list in my Nix config:

haskellPackages.ghc_9_2_1 # broken
haskellPackages.ghc-lib_9_2_1_20211101

The first is marked as broken, and when I rebuild NixOS the second gives me this error:

Setup: Encountered missing or private dependencies:
ghc-lib-parser ==9.2.1.20211101

I’m out of tricks. What should I do?

1 Like

Try (assuming you are following the unstable channel):

nix-shell -p haskell.compiler.ghc921 -c ghc --version

You do not have to add GHC for your configuration.nix. Try setting up a shell.nix for your project (or a flake). This will give you an isolated environment where you can explicitly control GHC version, libraries available etc. without the need to rebuild your system:

https://haskell4nix.readthedocs.io/nixpkgs-users-guide.html#how-to-create-ad-hoc-environments-for-nix-shell

Edit: With flakes or niv you can control the channels for this isolated environment, so you can use the unstable channel while your system follows a release channel, which is a typical pattern among NixOS users.

Solved! Thanks again, @wamserma!

In case anyone finds this useful, rather than use a complex call to nix-shell, I instead added the following default.nix file tot he project root and then ran nix-shell with no arguments before cabal repl:

with import <nixpkgs> { };
mkShell {
  buildInputs = [
    haskell.compiler.ghc921
  ];
}

After doing that I don’t need a with-compiler line in my cabal.project file.

1 Like

As a little pedantic nit, I’d suggest calling that file shell.nix instead - it works just the same for nix-shell, but shell.nix is the file intended to use for this, while default.nix is generally for a derivation containing your built software :slight_smile:

2 Likes

That does seem more natural. Done, thanks!

Glad you found your solution!

However be aware that using import <nixpkgs> means in many months or years you may come back and find your shell broken. The solution being pinning nixpkgs.

It’s quite likely you might not care about this case, but personally I usually pin by default so I can guarantee any shell I go into in any project I’ve ever looked at builds… because otherwise I get annoyed :smiley:

2 Likes

Personally I explicitly don’t pin my shells, because it forces nix to redownload whatever two year old software the shell used to depend on (given this’ll likely also include an old glibc and other annoying things, that can take long), and increases the number of different versions of a package on your system, which can lead to rapid disk space creep.

It’s sadly also no guarantee that the shell will work, because artifacts disappear from the internet, there is no source caching, and the upstream cache doesn’t persist binaries not present in an actual release (which can result in long build times too!). I’ve been bitten by this more than once.

If you pin it to the system nixpkgs you do occasionally run into packages disappearing, too, of course, and there’s no guarantee your software will build with the latest version of a package. But since both styles are a bit fragile, I think I prefer not pinning for dev shells.

2 Likes

the great thing about nix is that it allows you to run any number of versions of libs and apps with ease. However that’s the worse thing about nix too.