Workarounds for Haskell / cabal packages with constraints with Nix and Cabal?

1k views Asked by At

I recently got into developing with reflex-platform, with some extra configuration similar to what is described in the excellent reflex-project-skeleton.

Now I am having a package conflict that I am unable to resolve. I use the same cabal script as reflex-project-skeleton, which invokes nix-shell in non-interactive mode with a cabal command.

If I try

./cabal new-build --allow-newer all

I get

these derivations will be built:
  /nix/store/d6ji516i7pry5l6gv18y6hpj9k1bvgg5-heist-1.0.1.0.drv
  /nix/store/zj1clks7mzq8gn91ahhwa3nvpi5rwra9-snap-1.0.0.2.drv
  /nix/store/mx861972jnjabn7yxyr3y3q1yhf25jfq-snaplet-acid-state-0.2.7.drv
  /nix/store/grhp4dhavmpi6bgns5a6vdzg8ny2bsf8-hoogle-local-0.1.drv
  /nix/store/y3sszsj58f6ad3r06540w0mlr1pncd59-ghc-8.0.2-with-packages.drv

...

Configuring heist-1.0.1.0...
Setup: Encountered missing dependencies:
aeson >=0.6 && <1.2

builder for '/nix/store/d6ji516i7pry5l6gv18y6hpj9k1bvgg5-heist-1.0.1.0.drv' failed with exit code 1
cannot build derivation '/nix/store/y3sszsj58f6ad3r06540w0mlr1pncd59-ghc-8.0.2-with-packages.drv': 1 dependencies couldn't be built

The offending package appears to be snaplet-acid-state, so I tried installing it from inside the nix-shell:

cabal install snaplet-acid-state
Resolving dependencies...
cabal: Could not resolve dependencies:
trying: snaplet-acid-state-0.2.7 (user goal)
trying: base-4.9.1.0/installed-4.9... (dependency of snaplet-acid-state-0.2.7)
next goal: mtl (dependency of snaplet-acid-state-0.2.7)
rejecting: mtl-2.2.1/installed-BLK... (conflict: mtl =>
transformers==0.5.2.0/installed-0.5..., snaplet-acid-state =>
transformers>=0.3.0.0 && <0.5)
trying: mtl-2.2.2
next goal: transformers (dependency of snaplet-acid-state-0.2.7)
rejecting: transformers-0.5.2.0/installed-0.5..., transformers-0.5.5.0,
transformers-0.5.4.0, transformers-0.5.2.0, transformers-0.5.1.0,
transformers-0.5.0.1, transformers-0.5.0.0 (conflict: snaplet-acid-state =>
transformers>=0.3.0.0 && <0.5)
rejecting: transformers-0.4.3.0, transformers-0.4.2.0 (conflict:
base==4.9.1.0/installed-4.9..., transformers => base>=2 && <4.9)
rejecting: transformers-0.4.1.0 (conflict: base==4.9.1.0/installed-4.9...,
transformers => base>=2 && <4.8 || >=1.0 && <2)
rejecting: transformers-0.3.0.0 (conflict: mtl => transformers>=0.4 && <0.6)
rejecting: transformers-0.2.2.1, transformers-0.2.1.0, transformers-0.2.0.0,
transformers-0.1.4.0, transformers-0.1.3.0, transformers-0.1.1.0,
transformers-0.1.0.1, transformers-0.0.1.0, transformers-0.0.0.0,
transformers-0.5.3.1, transformers-0.5.3.0, transformers-0.5.0.2 (conflict:
snaplet-acid-state => transformers>=0.3.0.0 && <0.5)
rejecting: transformers-0.4.0.0 (conflict: base==4.9.1.0/installed-4.9...,
transformers => base>=2 && <4.8 || >=1.0 && <2)
rejecting: transformers-0.2.2.0, transformers-0.1.0.0 (conflict:
snaplet-acid-state => transformers>=0.3.0.0 && <0.5)
After searching the rest of the dependency tree exhaustively, these were the
goals I've had most trouble fulfilling: transformers, snap, base,
snaplet-acid-state, mtl

Tried specifying a version constraint in the cabal file, among other things, but to no effect.

Any clues? I'm not even sure what the exact issue is. Why is aeson failing to install in the first instance, and there is a conflict between snaplet-acid-state and mtl in the second?

1

There are 1 answers

1
Robert Hensing On BEST ANSWER

What happens with this cabal2nix workflow is that basically the dependency solver is forced to only consider the packages that have been provided by Nixpkgs, or in this case reflex-platform + Nixpkgs. By taking away the freedom to pick one of multiple versions, the Cabal dependency solver is reduced to a dependency checker.

Now, if the version bound is too strict, you can consider what is called 'jailbreaking' in Nixpkgs: removing all version bounds from the cabal file. The other option is to change package versions.

Gabriel Gonzalez has written a good explanation of version management with Nixpkgs' Haskell infrastructure. You may also check out this thread. It's a bit verbose, but it discusses the callHackage and callCabal2nix functions that are quite helpful.