Communities

Writing
Writing
Codidact Meta
Codidact Meta
The Great Outdoors
The Great Outdoors
Photography & Video
Photography & Video
Scientific Speculation
Scientific Speculation
Cooking
Cooking
Electrical Engineering
Electrical Engineering
Judaism
Judaism
Languages & Linguistics
Languages & Linguistics
Software Development
Software Development
Mathematics
Mathematics
Christianity
Christianity
Code Golf
Code Golf
Music
Music
Physics
Physics
Linux Systems
Linux Systems
Power Users
Power Users
Tabletop RPGs
Tabletop RPGs
Community Proposals
Community Proposals
tag:snake search within a tag
answers:0 unanswered questions
user:xxxx search by author id
score:0.5 posts with 0.5+ score
"snake oil" exact phrase
votes:4 posts with 4+ votes
created:<1w created < 1 week ago
post_type:xxxx type of post
Search help
Notifications
Mark all as read See all your notifications »
Q&A

Welcome to Software Development on Codidact!

Will you help us build our independent community of developers helping developers? We're small and trying to grow. We welcome questions about all aspects of software development, from design to code to QA and more. Got questions? Got answers? Got code you'd like someone to review? Please join us.

Post History

75%
+4 −0
Q&A Differences between Haskell tools Stack and Cabal?

The short, broad strokes answer is that (modern) cabal-install uses a nix-style approach where there's a shared global cache, but you can have multiple versions of a package installed or even the s...

posted 2mo ago by Derek Elkins‭

Answer
#1: Initial revision by user avatar Derek Elkins‭ · 2024-09-30T04:22:05Z (about 2 months ago)
The short, broad strokes answer is that (modern) `cabal-install` uses a nix-style approach where there's a shared global cache, but you can have multiple versions of a package installed or even the same version of a package installed with different versions of its dependencies. `stack` takes an approach similar to a typical Linux OS package manager where there's a "blessed" set of versions of packages that are semi-manually verified to work well together.

There are some other smaller or more situational differences. For example, `stack` will install GHC binaries, but nowadays you should probably use [GHCup](https://www.haskell.org/ghcup/) for that.

If you don't have strong feelings about either of the above approaches to package management, then, personally, I'd recommend starting with `cabal-install`. It seems some tooling may work better out of the box with it, and it's not going anywhere. That said, for simple, basic usage, the experience with either should be more or less the same. Both provide a `cmd install some_package` experience developers have come to expect.

----

Elaborating a bit. First, while I analogized `stack` to an OS package manager, unlike such a package manager, you can easily have different project use different "snapshots" of packages, so it's not as all-or-nothing as an OS package manager.

Similarly, while (modern) `cabal-install` uses a nix-like approach, it doesn't require the relatively complicated `.nix` files of actual nix. Also, unlike many other popular language package managers, e.g. `pip` or `npm`, `cabal-install` has had a fairly sophisticated solver throughout much of its life^[C#'s NuGet only [announced](https://devblogs.microsoft.com/nuget/introducing-nugetsolver-a-powerful-tool-for-resolving-nuget-dependency-conflicts-in-visual-studio/) such a thing this year.]. This means, modulo the accuracy of the version bounds provided by libraries, it can provide a working build plan if one exists.

----

Some historical context may also be useful.

To start, a standard disclaimer is that "Cabal" refers to multiple aspects of the package management infrastructure for Haskell. It refers to the Cabal framework, the Cabal library, the `.cabal` file format, and, of course, to the `cabal-install` tool. `stack` builds on the underlying Cabal infrastructure, and the main difference is between the `stack` and `cabal-install` tools.

Cabal goes back to the Library Infrastructure Project in 2003 and its first release in 2005^[I think many people don't really appreciate just how old Haskell - the first Haskell Report came out April 1st, 1990 - and its tooling is.]. You can look at the [original Library Infrastructure Project proposal](https://www.haskell.org/cabal/proposal-1.0/) to see what other systems they were looking at. The original versions of `cabal-install` used a global package store which, while much better than the nothing that preceded it, was pretty disastrous. That said, even very early on, a nix-like approach (Nix being a fairly new and interesting project in this timeframe) was an aspirational goal for `cabal-install`. However, what followed was a "sandbox" approach where each of your projects had its own collection of packages. This pattern is (now) very familiar from tools like `npm` or Python virtual environments.

It was during this [era](https://gist.github.com/parsonsmatt/0d75877ea14974647621b21f8492fb43) that Stackage circa 2012 and `stack` circa 2015 started. Stackage preceded cabal sandboxes, while `stack` followed their existence. Stackage was a response to the "Cabal hell" due to global repositories and limitations of the solver at the time. `stack` was created to address UX issues around using Stackage with `cabal-install` as well as other missing features of `cabal-install`. You can see a retrospective circa 2018 on `stack` by one of its original creators [here](https://www.snoyman.com/blog/2018/11/stackage-history-philosophy-future/).

It is no secret that this period was marked by quite a lot of acrimony due to "forking" the main build tool. On the one side, many of the issues that `stack` was addressing had solutions or had solutions in development when `stack` was created, and so it would seem better to avoid duplicating effort and downstream effort and potentially fragmenting the community. On the other hand, it seems clear that some features of `stack` were never going to be incorporated into `cabal-install`, and even if they were, it would take a long time. There were also some "personality" conflicts that amplified these issues.

In 2019, the nix-style approach, which had been a v2/new-build option for several years, became the default for `cabal-install`. While sandboxes and improvements to the solver resolved much of "Cabal hell", the nix-style builds do still do a good job of getting the benefits of sandboxes (different per-project versions of things and isolation) while avoiding many of the downsides (duplicate copies, redundant builds). There are some things sandboxes make nicer, so them being removed entirely from `cabal-install` is a bit annoying, though technically you can get a similar experience with a local package environment. There's [talk](https://github.com/haskell/cabal/issues/10098) about re-adding a sandbox experience on top of the nix-style builds.

My vague impression is that `stack` has lost a lot of the momentum it had in the past, while `cabal-install` has gained momentum. `stack` had the benefit of being commercially backed from the start, while `cabal-install`, like a lot of development in Haskell, had been entirely volunteer-driven. Haskell has gotten a lot more explicit industry support over time which I think has led to `cabal-install` development moving faster than it had in the past. As mentioned even in the 2018 retrospective above, `cabal-install` has resolved most of the most painful issues that motivated `stack`. As I said at the very beginning, the differences in package management philosophy are, in my opinion, the core distinctions which aren't likely to come together anytime soon. Arguably, that's more about using *Stackage* rather than `stack`.

Personally, as someone who's essentially never used Stackage nor `stack`, I would appreciate "official" support for Stackage in `cabal-install`. I probably still wouldn't use it most of the time, but the "curated" package sets that Stackage provides do solve real problems. Not every incompatibility is going reflected in version bounds or even a successful compile. That said, especially once sandboxes were introduced, I've only rarely had incompatibility issues and many of them were inherent and thus not solvable by using `stack`. More broadly, for my purposes limited and out-of-date packages in OS distributions have caused me more frustration than unexpected incompatibilities. Others have different values and experiences.