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.

Differences between Haskell tools Stack and Cabal?

+5
−0

Haskell tooling can be confusing. Both Stack and Cabal appear to be build tools with similar goals.

How do they differ? Why should you pick one over the other?

History
Why does this post require attention from curators or moderators?
You might want to add some details to your flag.
Why should this post be closed?

0 comment threads

1 answer

+4
−0

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 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[1]. 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[2]. You can look at the original Library Infrastructure Project proposal 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 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.

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 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.


  1. C#'s NuGet only announced such a thing this year. ↩︎

  2. 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. ↩︎

History
Why does this post require attention from curators or moderators?
You might want to add some details to your flag.

0 comment threads

Sign up to answer this question »