I was under the impression that the cabal.project.freeze file generated by cabal freeze was supposed to lock the exact version of all the dependencies used by your package. I was therefore surprised to see something like this in my freeze file
Freeze should only use equals. Anything else is a bug on its face.
I think the lack of good and easy lockfile support is Haskellβs one weakness compared to mainstream language package managers. Itβs not complicated but cabal doesnβt do it well.
When my deps are in Stackage, yeah. But cabaldoes tend to work well for most things in Hackage, which is really nice. The main pain point is the impurity of your Hackage index which in turns causes your plan to change as you cabal update.
The freeze file is kind of like a Stackage a la carte for my individual project - a set of versions known to build together.
I guess I find that pinning index-state achieves pretty much everything I would want from a freeze file. I donβt know if itβs bulletproof, but in practice it makes everyone get the same plan which is what I want anyway. And it has the virtue that you can change version bounds etc without having to regenerate something, you only need to change it if you want something newer.
Does cabal guarantee that the plan wonβt change across cabal versions? Thatβs the only other thing I can think of.
That said, I think checking in a freeze file is still nice because it makes versions explicit in source instead of implicit. I think thatβs one appeal of them in other languageβs tooling too.
On stack you can use extra-deps in your stack.yaml to list any hackage or git repos you want, eg βpandoc-1.2.3β, that arenβt in stackage. The lock file was implemented in 2019, which does the expected locking down of precise content hashes. As you describe, itβs like generating your own stackage snapshot βplus extra ones,β with the same guarantees. It checks version bounds for you.
Stack itself pulls packages from https://casa.stackage.org/, which is a content addressed storage (hash of the contents), to better enable this workflow.
No, stack doesnβt do that (currently; it used to run cabalβs solver a few years back). For solving, you want cabal.
^ This is what I was replying to, it seemed you might have overlooked stack which was designed for this and does it well.
But perhaps youβre wishing for a tool that nails both solving and freezing (smart dependency search for easy experimentation and dealing with less-maintained software; reproducibility for production). Iβd like that too.
Updo, a tool for generating projects, has specific targets for Stack and Cabal but the default target generates projects for Stack and Cabal at the same time (Cabal before Stack). The upshot of running Updo this way is that Cabal projects get to use stackage (as much or as little as you please) and both Cabalβs freeze file (to see what the solver picked) and Stack suggest what exact version equality constraints to use for packages (for versions of packages either not in a resolver or that need overriding).
Some things that would help improve Updo;
If with Cabal, version equality constraints could be overridden
If with Cabal, we could specify hackage revisions (some-package == x.y.z@rev:1)
If with Stack, we could specify fine-grained allow-newer
With Updo, it is reasonably easy to combine the benefits of stackage package sets and solving for versions of packages outside those sets.
On lock files; I recommend committing Stackβs lock file but wouldnβt recommend committing Cabalβs lock file (the freeze file) as they vary by platform.
Thanks for those comments. Updo sounds powerful, though personally the prospect of adding another layer on top of all the same existing tools is a little scary (as is dhall).