It's 2018. We still have
cabal install but no
cabal uninstall. This is not
okay; it has never been okay; it will never be okay; no reasonable person would
be okay with this; in no universe is this okay.
This is not, however, the reason for my most recent trip to Cabal hell. No, my
most recent Cabal issue was refreshingly straightforward: running
caused any subsequent
cabal list to crash — with an error message
“helpfully” suggesting that
cabal update might fix things. A
tool should not break itself!
After some investigation,
cabal update appeared to have downloaded a file
cabal list could not parse. This is silly. Cabal should verify the file
parses after downloading it and throw it away (with a warning) if it doesn't!
Moreover, the error
cabal list produced was:
internal error when reading package index: failed to parse .cabal file
This message is useless garbage. I don't have a
.cabal file. I do have a
~/.cabal directory, so presumably the offending "package index" is somewhere
in there. Where? God only knows.
It is at this point I lost patience and nuked
~/.cabal for the
If Cabal is hell, Stack is purgatory
stack is a modern, cross-platform build tool for Haskell code. [...]
stack has also been designed from the ground up to be user friendly, with an intuitive, discoverable command line interface.
Lovely! I'll just run
stack help to get my bearings, then...
$ stack help Invalid argument `help' Auxiliary command not found in path `stack-help' File does not exist or is not a regular file `help' [... et cetera ...]
This is dumb. Obviously I want help. Apparently the right thing to do is:
$ stack --help
But this produces multiple pages of output, so I have to pipe it to
less to read it. It should do this automatically! If you're not
going to have a
man page (and Stack doesn't), your help command must be at
least as usable as a
$ stack --help init
does not produce help for the
init command. This is dumb. Obviously I want
help for the
init command. Stack should learn from
git here —
each of the following should work and do the same thing:
stack help init;
stack --help init; and
stack init --help.
Give me hypermedia or give me death
Even once you stumble upon the correct incantation, Stack's help is quite vague:
$ stack init --help Usage: stack init [DIRS] [--solver] [--omit-packages] [--force] [--ignore-subdirs] [--help] Create stack project config from cabal or hpack package specifications [... et cetera ...]
Erm, what does it do?
“Create stack project config from cabal or hpack package specifications”?
I have no idea what this means. I came to Stack to avoid Cabal. Every interaction I've had with Cabal has been a combination of mystifying and frustrating. I don't ever want to hear the word "Cabal" again if I can avoid it. Don't make me understand the crappy tool you replace in order to use your new, better one!
Besides which, this explains nothing. What is a Stack project config? What is
a Cabal/hpack specification? When and why would I want to turn one into the
other, and how does stack go about doing it? If you claim to be friendly to new
users, you must answer these questions. At a bare minimum, point the user to a
reference which does answer these questions — after all,
man pages can
man pages, and web pages can link to other web pages.
Documentation should be hyperlinked!
At least Stack can uninstall, right?
Well, about that...
$ stack install --help [... help for 'stack install' ...] $ stack uninstall --help Usage: stack uninstall [IGNORED] [--help]
DEPRECATED: This command performs no actions, and is present for documentation only
uninstall is still unforgivable.
Yes, I know stack isn't really a package manager; and yes, I know
install is just an alias for
stack build --copy-bins, which blindly copies a
bunch of binary files into
~/.local/bin. None of this is a good excuse. If
stack isn't a package manager, it shouldn't pretend to be one by having an
install command lying around like a loaded footgun.
Isn't it about time Haskell had a decent package manager, anyway? It's 2018!
Projects are an unnecessary barrier to entry
Stack assumes that if you want to use it, the first thing you'll do is set up a
stack new. This makes me grumble. I shouldn't need a "project"
with a fixed directory structure just to get up and running. I don't want to
jump through your arbitrary hoops. I have a single goddamn file that needs a
particular library. I want to install it, with the ability to uninstall or
upgrade or replace it later, and move on with my life.
I'll make a project when the thing I'm building needs a project, which is probably never, because most of my code is throwaway code exploring interesting concepts, because I'm an academic and a hobbyist. Hell, I suspect most code is throwaway code anyway. (Moreover, every "project" structure I've ever seen has way too many goddamn files.)
For a language ecosystem which gets this mostly right, try Racket.
I eventually got the crash bug fixed by prodding some Cabal folks on IRC. They were very helpful and polite and I really don't want to rag on their hard work, but the fact that this bug could happen at all is frustrating. It's indicative of architectural flaws: verify what you download! have useful error messages! and for Christ's sake, don't have