Use Hpack, and you don’t have to manually add/remove modules in the cabal file’s
Haskell has a very long history: Since 1987 which is long before the concept of “package managers.” When modern package management emerged, Haskellers had to invent something too. So they made “Cabal” which came to mean three things:
(This is why you should be careful about what someone means when they say “Cabal.”)
And then there is
cabal-install which is different from “Cabal.”
cabal-install is a command line application that lets you manage Cabal-based projects.
So, we had commands like
cabal-install, and we were happier than before. Until the programming community realized the problem of dependency hell; which package depends to which version of which library, etc. Naturally, we needed some kind of sandboxing per project, so we added that to cabal. That’s called Cabal sandbox. The problem was, although Cabal sandbox did solve the problem of dependencies-per-project,
Stack solved these problems. Stack is actually a wrapper (plus some great deal of its own machinery) around the commands like
cabal-install. It does a brilliant job to isolate everything (both compilers and dependency packages) and sharing a binary if it can be shared.
For example, if you already have a bytestring-0.10 that was built using base-4.8, you don’t have to build it again when it’s needed because it’s cached. However, when you need base-4.9 and bytestring-0.10 in your project, you’ll have to build bytestring from scratch; this is exactly the behavior we want.
One of the remaining problems is that the
<projectname>.cabal file is in a custom format. Custom formats are generally not good because you can’t leverage the existing tools and free-ride other people’s work. Another pain point of the cabal files is that, whenever you add or remove some module (Haskell source code file) to/from your project, you have to edit the
other-modules section of the cabal file. Tedious, error-prone, and not so rewarding.
We understand that the concept of cabal file and its format came out before the popularization of YAML or TOML or anything, and we also understand that if Cabal decided to switch from
package.yaml, it would be a breaking change. But maybe we can write some code to
Fortunately, someone already did this. It’s called Hpack.
Hpack is built into Stack, so there is no additional setup required. This is so brilliant.
If you already have a Haskell project, use hpack-convert. It will automatically generate a
package.yaml file from your
If you are starting a new Haskell project, use Haskeleton. It’s simple:
stack new haskeleton myprojectname -p 'github-username:xtendo-org' -p 'author-name:XT'
Actually, my truly favorite thing about hpack is that you can specify a common set of dependencies that get shared across all the libraries/exes/tests/benchmarks in your setup. That part is truly annoying in cabal files.
You can do the same thing with ghc-options, language extensions, etc.
I totally agree.