Personally, I like to follow the mantra cabal is not a package manager. Because whenever I treat it like one, I get messed up in a bad way. I buy in to this argument[1] as to why it isn't.
That argument seems more like (ignoring the naming issues of cabal vs cabal-install), that cabal is a terrible package manager, but still (to me) seems to bare all the major features of a package manager.
The fact that it forwards package registration to the underlying ghc-pkg system, has very poor/nearly nonexistent record keeping, and can't perform uninstall operations are kinda crucial. I've never heard of a packager manager that can't uninstall.
If you present it as a package manager, even if it's a bad one, then you also telegraph a certain amount of implied functionality, and in turn the user has a certain level of confidence that the system is smart enough to do its best to prevent you from damaging your package ecosystem (not a guarantee, but at least an effort); cabal and by extension cabal-install doesn't provide this at all. It simply provides a way to install packages and makes a best effort at meeting the build goals required for individual commands to succeed in a vacuum.
I hesitate to call that a package "manager". It's just a very mediocre package installer.
Actually nix is a pretty awesome package manager for haskell. All my projects now have a default.nix and a shell.nix and I have this little snippet in emacs:
This drops you into a nix shell with all the dependencies for the project you're working on present.
You can also (especially easy if you're using projectile) run compile with the command nix-shell -I . shell.nix --command "cabal configure; cabal build" and that give you a nice list of type errors in your current project.
Repeatable builds with no cabal hell. In the words of disney: "I'm never going back, the past is in the past!"
[1]: http://ivanmiljenovic.wordpress.com/2010/03/15/repeat-after-...