cabal usage notes
Follow along in bash to see the effects of all the commands in this post.
mkdir ~/sandbox-play cd ~/sandbox-play
Play in a sandbox
If you're not already starting all your projects with the cabal sandbox command, then you might consider beginning today. If you're a haskeller then this is the fastest way to save yourself from dealing with the cabal hell caused by installing all the dependencies for your various projects into the global or user-level registries.
mkdir super-giraffe-game # your project directory cd super-giraffe-game cabal sandbox init ls -la
Now any cabal install commands you run in the project directory will install to a subdirectory. This goes for all the cabal commands in this post. Here we install the utility-ht package to the sandbox.
cabal install utility-ht
You can list what's been installed to the sandbox with the following command. It'll be all the packages after the path to your sandbox.
cabal sandbox hc-pkg list ... xhtml-3000.2.1 zlib-0.5.4.1 /Users/f06code/sandbox-play/super-giraffe-game/.cabal-sandbox/x86_64-osx-ghc-7.6.3-packages.conf.d utility-ht-0.0.10
You might want to unregister packages from a sandbox too. You can use the following command.
cabal sandbox hc-pkg unregister utility-ht
Share the sandbox
An even better habit to start is the use of shared sandboxes. When you have multiple projects which use the same dependencies, shared sandboxes mean that you only have to install things once. Let's change your project directory to use a shared sandbox.
rm -r cabal.sandbox.config .cabal-sandbox/ cabal sandbox init --sandbox ~/sandbox-play/playpen ls . ../playpen/
You can use that second command with the absolute path to playpen from any project directory on your system, and all will use the same sandbox. Sandboxes contain absolute paths in their configuration files. Make sure you create your sandboxes in a directory where you won't mind them staying.
Look before you leap
Always check what will happen before performing a cabal install. This will help you recognize likely cabal hell situations in the future before they crop up. Let's do this for the GPipe package.
cabal install GPipe --dry-run -v
This will print out the required dependencies of the target package in order of planned installation, and it will tell you if each package is completely new or just a new version of an existing package. New versions frequently put you in cabal hell, and you can sometimes reduce them by adding --avoid-reinstalls to a cabal install command.
You can tweak the install plan by including multiple package names or including a package version after any package name.
cabal install containers-0.5 GPipe --dry-run -v # use a specific version of containers
When you're satisfied with the install plan, remove both --dry-run and -v to install. Cross your fingers, because this is where you might end up in cabal hell. Don't actually do this today.
Aside: If you actually do want to install GPipe with haskell-platform: stable 2013.2.0.0 then follow these instructions which have fewer dependencies.
You can also look before you leap when installing the dependencies for a package you've cloned or are building yourself. Simply leave off the package name from the install command and include --dependencies-only, as I've done on the last command in this paragraph.
cd ~/sandbox-play/ cabal get GPipe cd GPipe-*/ cabal sandbox init --sandbox ~/sandbox-play/playpen cabal install --dependencies-only --dry-run -v
Shared sandboxes are a useful tool for escaping the cabal hell that occurs when a dependency fails to compile. You just clone the correct version of the failing dependency, link it to your project's shared sandbox, and fix it.
Get out of hell
Don't execute any of the commands below; they're for a hypothetical fix.
Hypothetical Situation
You installed some dependencies for a package you are working on and it ended with "error" or some other useless dribble. Cabal happily installed all the other planned packages excepting those that depended on the failed package. This means that the actual error is likely not on your screen.
Recommended Solution
Re-run the previous installation command. Cabal won't re-install any of the successful packages. You'll see the compiler or cabal error for the failed package at the bottom of your screen this time. If you are confident, you can try to fix the package by delving into its source:
cd .. # get out of your project directory cabal get [package[-version]] # download source for the failed package cd [package[-version]] cabal sandbox init --sandbox [your project's shared sandbox] cabal install --dependencies-only --dry-run -v # should report no dependencies are required
Now you can fix the source of the failed package. If you think your work is done, try to build with:
cabal build
Once it's working you can cabal install your fixed version into the shared sandbox.
cabal install
Now when you return to your project directory and run your original dependency installation command, it works!
Happy packaging.













