Easier to use stackage resolvers

The Haskell Foundation announced that they’ll be providing a new home for Stackage.

Stackage resolvers are easy to use from Stack. Take the package set from stackage as a resolver and put any packages missing from the set or package version overrides (newer or older or pinned revisions) in the project settings; in stack.yaml as extra-deps.

It may not be obvious but Stackage also provides cabal.config package sets for use by Cabal projects.

import: https://www.stackage.org/nightly-2023-12-07/cabal.config

But let’s say I want a different version of a package with that nightly resolver. Picking hashable for no particular reason, I might want an older version:

packages: .
import: https://www.stackage.org/nightly-2023-12-07/cabal.config
constraints: hashable ==1.4.2.0

In a Stack project we can do this:

packages: ["."]
resolver: nightly-2023-12-07
extra-deps: [hashable-1.4.2.0]
$ stack build --dry-run
...
Would build:
...
* hashable-1.4.2.0: database=snapshot, source=hashable (from Hackage)

If I hadn’t put extra-deps: [hashable-1.4.2.0] then we’d get the version from the resolver’s package set, hashable-1.4.3.0.

Let’s now build the same thing with Cabal:

$ cabal build all --dry-run
Resolving dependencies...
Error: cabal: Could not resolve dependencies:
[__0] trying: cabal-version-override-0.1.0.0 (user goal)
[__1] next goal: hashable (dependency of cabal-version-override)
[__1] rejecting: hashable-1.4.3.0 (constraint from project config /.../cabal.project requires ==1.4.2.0)
[__1] rejecting: hashable-1.4.2.0, hashable-1.4.1.0, hashable-1.4.0.2,
hashable-1.4.0.1, hashable-1.4.0.0, hashable-1.3.5.0, hashable-1.3.4.1,
hashable-1.3.4.0, hashable-1.3.3.0, hashable-1.3.2.0, hashable-1.3.1.0,
hashable-1.3.0.0, hashable-1.2.7.0, hashable-1.2.6.1, hashable-1.2.6.0,
hashable-1.2.5.0, hashable-1.2.4.0, hashable-1.2.3.3, hashable-1.2.3.2,
hashable-1.2.3.1, hashable-1.2.3.0, hashable-1.2.2.0, hashable-1.2.1.0,
hashable-1.2.0.10, hashable-1.2.0.9, hashable-1.2.0.8, hashable-1.2.0.7,
hashable-1.2.0.6, hashable-1.2.0.5, hashable-1.2.0.4, hashable-1.2.0.3,
hashable-1.2.0.2, hashable-1.2.0.1, hashable-1.2.0.0, hashable-1.1.2.5,
hashable-1.1.2.4, hashable-1.1.2.3, hashable-1.1.2.2, hashable-1.1.2.1,
hashable-1.1.2.0, hashable-1.1.1.0, hashable-1.1.0.0, hashable-1.0.1.1,
hashable-1.0.1.0, hashable-1.0.0 (constraint from project config
https://www.stackage.org/nightly-2023-12-07/cabal.config requires ==1.4.3.0)
[__1] fail (backjumping, conflict set: cabal-version-override, hashable)
After searching the rest of the dependency tree exhaustively, these were the
goals I've had most trouble fulfilling: hashable, cabal-version-override

The problem is that Cabal constraints are additive and we can’t solve for both hashable ==1.4.3.0 and hashable ==1.4.2.0 as there is no version that satisfies both constraints.

Our intent is clear and can be achieved by pruning the stackage package set on-the-fly so our versions don’t create unsolvable version conflicts.

I’ve made a pull request that does this, #9510 Override imported package version equalities. This enhancement to Cabal avoids the current workaround of having to download the cabal.config and comment out conflicts manually.

I’m the author of Updo. While Updo can work by taking resolvers straight from stackage, having to download a stackage resolver’s cabal.config manually and then edit it when there is a version conflict is probably the biggest ask of users of that tool. This is the last step, the “Fixup Unsatisfiable Version Constraints” step in introducing Updo to a project.

Another usability improvement for Cabal that would help Updo, is being able to pin to revisions with a @rev:n syntax.

From the long discussion on RFC: Cabal support for LTS Snapshots we should prune related flag constraints too.

9 Likes