I find it really interesting how a the success of programming language (or project) is a combination of multiple factors that aren't necessarily correlated -- like for example, the Haskell community is full of really genuinely nice people while the Linux kernel community is full of screaming. Or how lisp is famously great except that there's multiple incompatible implementations; there's nothing about lisp itself that causes that. And similarly in this case: there's nothing inherent about Haskell that required the versioning mess it seems to have* .
In all these cases there are some weak correlation: perhaps the research origins of Haskell led to a culture of respectful disagreement, perhaps the flexibility of lisp implies more differences of opinions, perhaps extra-powerful static typing leads to more breaking APIs on version bumps. But that's not enough to fully explain it. A lot of it is just how things turned out.
In an imaginary world I'd be able to just read the language spec and have enough info to judge whether to base my next project on something, but it turns out there are all these "soft" factors that matter just as much.
* You could imagine for example a different design where you get a separate copy of all needed libraries for each project so that they never stomp on each other (like what the various fooenv tools do for ruby/python/etc.). It has different tradeoffs, sure, but it at least superficially seems it would reduce frustrations like in this post.
I'm disappointed to hear the Haskell toolchain is so problematic, as I was looking forward to trying Yesod.
Everyone goes crazy over syntax and idioms and OMG GROUNDBREAKING NEW IDEAS (not) when really 85% of a language depends on the library and toolchain.
A programming language is not just a spec and a syntax, it's also a way of seeing the world - "The limits of my language mean the limits of my world.", so to get a new way of looking at things, you also need to reinvent the basics to some extent, and rethink how (for example) basics like errors, threads or strings are handled.
Personally, I think it's useful to have a multipolar programming landscape, even if it sometimes leads to duplicated work, because it can give you a fresh perspective on old problems.
I'm hardly an advanced Cabalist, but it does the job nicely for me, and is quite stable at that too. Like virtualenv, it can also create a "sandboxed" GHC, so even system-level updates to GHC don't wreak havoc in your projects.
They're not needless, it was presumably done for congruency with the nadsat subheaders:
Yes, it does. cabal-dev can install a fully hermetic package database if you ask it to, but by default it only installs packages that aren't already present in your global package db.
I don't understand why he wanted to reinstall things so often; it would have been much easier (and certainly faster) to just install libraries once.
The first problem is that he didn't read any of the Cabal documentation. He complains that after upgrading his Cabal binary, that it still complains that an update is needed. I'm almost certain this is because he hasn't put the Cabal binary directory (~/.cabal/bin) on his $PATH. While this is arguably something that Cabal should be detecting and warning about, it's also not a requirement unique to Haskell -- any package manager that installs to a user's home directory will need them to change their $PATH.
Continuing on, he installs cabal-dev (good!), then proceeds to not use it. Instead, he tries to jam all of Yesod (a notoriously version-picky package) into his global package directory.
Then he uses cabal-dev to build his new site, and here's where things get weird. It should absolutely not install anything other than what his particular package needs as dependencies. If it's installing the world again, then there is something horribly misconfigured on his system.
Finally, I strongly object to Yesod being considered a "success story". While web frameworks are currently the hip thing, and Yesod is indeed a web framework, to my knowledge it's gained no significant userbase in part due to the huge nest of conflicting library versions that it depends on.
Here's what he needs to do:
# Clean up whatever mess he's currently made
$ rm -rf ~/.cabal ~/.ghc
# Re-initialize Cabal
$ export PATH="$HOME/.cabal/bin:$PATH" # optionally add to .bashrc
$ cabal update
$ cabal install cabal-install cabal-dev
# Assuming that Yesod is using standard Haskell packaging properly, this
# should install Yesod in its own little sandbox so it won't destroy the rest
# of the system.
$ mkdir my-yesod-project
$ cd my-yesod-project
$ export PATH="$PWD/cabal-dev/bin:$PATH"
$ cabal-dev install yesod
# Now Yesod can be used without fear
$ yesod init .
$ cabal-dev install
Contrary to the thesis of the post, the haskell community seems to be well aware of this, and there are several attempts to fix it being actively worked on, just nothing particularly standardized yet. Meanwhile, cabal-dev lets people get work done.
> Ideally, getting a basic setup going shouldn't take a
> deep-read of the docs of my package manager.
>Please name one package manager which installs binaries to the user's home directory, but doesn't require updating the user's $PATH.
Do you even realize how little those two statements follow each other? The whole red herring argument here is kind of annoying, but I'll hit it anyways- every package manager that I've used which installs binaries (or anything, really) in the user's home directory (or any directory really) does make me update the path- but it also tells me this and gives me sane errors when that hasn't happened.
2. Ivy/Maven. Dependencies are placed in ~/.ivy, and are available for use without changing environment variables.
3. rubygems. A ~/.gems directory is created that provides dependencies by ruby version, if you wish.
Now, running a clis still requires an addition to path. But package managers do exist that organize dependencies on the user path without explicit environment variable edition.
The problem he reports is that when he upgrades the Cabal binary by running 'cabal install cabal-install', the sequence of events is:
1. The system runs /usr/bin/cabal
2. Cabal fetches and builds the new binary
3. The new binary is installed to $HOME/.cabal/bin/
4. When he runs 'cabal update' again, it still uses /usr/bin/cabal because $HOME/.cabal/bin/ is not on his $PATH
One thing that is wrong is the lack of "semantic versioning". There is the Package Versioning Policy (http://www.haskell.org/haskellwiki/Package_versioning_policy), and most packages now adhere to it. Granted, its prescriptions differ from "semantic versioning", and some people disagree that Haskell packages should specify such restrictive versioning boundaries all the time.
(The PVP essentially says that for a version a.b.c.d, every change of a or b means that the API might have changed. Now it might be that most packages are not even affected by the change...)
"Major version X (X.y.z | X > 0) MUST be incremented if any backwards incompatible changes are introduced to the public API. It MAY include minor and patch level changes. Patch and minor version MUST be reset to 0 when major version is incremented."
Meanwhile the PVP lets you get away with just updating the minor version there.
References(for those who are interested)
Hopefully the guys at FP complete will redirect some of their focus onto this (please oh please).
If this rather rude character is repulsed by Haskell then I think the community is probably better for it.
On second thought, people this rude should stay away from Haskell.
Catch-22, he can't contribute if he can't bootstrap a development environment :)