Haskell is a general purpose, purely functional, programming language.
- 1 Installation
- 2 Problems with linking
- 3 Managing Haskell packages
- 4 See also
Haskell generates machine code that can be run natively on Linux. There is nothing special required to run a binary (already compiled) software, like the ones provided in the official repositories. On the other side, AUR packages or source codes requires a compiler to build the software.
Installing the compiler alone permits to build Haskell source code. A few additional tools are needed for development work.
To build a Haskell source code into native code, a compiler must be installed. There are several implementations available, but the one used most (which is now de facto the reference) is the GHC (Glasgow Haskell Compiler). It is available in the official repositories as .
You can try it with the following file:
main = putStrLn "Hello, World"
and by running:
$ ghc -dynamic Main.hs $ ./Main
Since version 8.0.2-1, the Arch package no longer installs static versions of the GHC boot libraries by default, nor do any of the haskell-* packages in community. Therefore, to link successfully one must pass the
-dynamic flag to GHC, as the default is to use static linking. For Cabal, this amounts to the following configuration:
cabal configure --disable-library-vanilla --enable-shared --enable-executable-dynamic --ghc-options=-dynamic
--disable-library-vanillasuppresses the creation of static libraries (if your project contains a library).
--enable-sharedenables the creation of shared libraries (if your project contains a library).
--enable-executable-dynamiccauses dynamic linking to be used for executables (if your project contains executables).
-dynamicflag to every invocation of GHC (e.g. if a package has a non-trivial
Note that if you've used gchup to install cabal, adding these changes to your
$HOME/.cabal/config should not be done. This can lead to errors such as
dieVerbatim: user error (cabal: '/home/user/.ghcup/bin/ghc'.
You can also set these flags in
~/.cabal/config so that it applies to all projects by default:
library-vanilla: False shared: True executable-dynamic: True program-default-options ghc-options: -dynamic
Dynamic linking is used for most Haskell modules packaged through pacman and some packages in the AUR. Since GHC provides no ABI compatibility between compiler releases, static linking is often the preferred option for local development outside of the package system.
To use static linking, one must, at minimum, install the static boot libraries through the
Unfortunately, if your project depends on any of the
haskell-* packages that you have installed, Cabal does not take the absence of static libraries into account during dependency resolution. As a result, it will try to use the existing
haskell-* package and then fail with linker errors when it realizes the static libraries are missing. Unlike
ghc-static, there are no “
haskell-*-static” packages to fix this problem.
To work around this problem, you can install
/usr/share/ghc-pristine, with a package database that contains only boot libraries. Then, to build software with static linking, one simply needs to invoke the wrapped compiler
/usr/share/ghc-pristine/bin/ghc. For Cabal, this amounts to the following configuration:
cabal configure --with-compiler=/usr/share/ghc-pristine/bin/ghc
This can be made permanent by editing
~/.cabal/config (it can be created using
cabal user-config init). Be aware that you still need
- One could manually run
cabal install --force-reinstallsto shadow the corresponding
haskell-*packages. This can be tedious as you must explicitly enumerate all transitive dependencies that coincide with an existing
- Use a completely separate GHC distribution: download the official Linux binaries for GHC and cabal-install and unpack them somewhere else. This is in effect what
ghc-pristineuses less disk space.
This section explains how to install
cabal-install but from Hackage instead of the official package from the repositories. This
cabal-install will build Haskell packages without using shared libraries unlike the official which requires you to link dynamically.
In theory with any
cabal-install you could choose between both methods, static and dynamic, for linking your Haskell code. In practice because in Arch some basic Haskell libraries (
haskell-* packages) are provided as shared objects (
.so files) and those libraries are globally registered in Cabal, it has trouble using the same libraries for static linking. To avoid linking errors, it's also especially important to not to mix statically and dynamically Haskell packages installed on the same system, as Cabal doesn't fetch a required package once it has been globally registered (check them with the command
ghc-pkg list) in one of its forms and not the other (independently of the linking type of the package that it's needed).
For these reasons, you have to make sure that the only two related Haskell packages you have installed are broken link: package not found], and none of the
haskell-* dynamic libraries available in the official repositories).
You can also use Stack as an alternative build tool for Haskell packages, which will link statically by default. But if you still want to use Cabal to build using static linking, follow the next steps of this section to install your own compiled
cabal-install from Hackage. For this purpose we are going to use the tool Stack that will help us fetching all the dependencies required and building your own
First you have to install
haskell-* dynamic libraries.
Then prepare Stack downloading the package index. Stack will be used with the only purpose of bootstrapping the compilation of your own
cabal-install but using the already installed compiler:
$ stack setup --system-ghc
Now install your own
$ stack install --system-ghc cabal-install
This newly installed
cabal-install has been compiled without shared libraries and won't use them when building packages by default. Also, this
cabal-install will use the installed compiler.
Alternatively, you can also use
cabal-install binary and even a specific version of
ghc compiler. See the usage section to see the steps to follow.
Haskell development tools
To start developing in Haskell easily, one option is the haskell-platform bundle which is described as:
- The easiest way to get started with programming Haskell. It comes with all you need to get up and running. Think of it as "Haskell: batteries included".
- ghc (boot libraries ( ). Static boot libraries ( ) must be separately installed. ) — Compiler, which only comes with dynamic
- cabal-install ( ) — A build tool focused on dependency resolution and sources packages from Hackage
- stack ( ) — A build tool focused on curated snapshots and sources packages from Stackage
- haddock ( ) — Tools for generating documentation
- alex ( ) — Lexical analyzer generator
- happy ( ) — Parser generator
Alternatively, you can use Arch Linux install instructions.to manage your Haskell environment by following the
Managing Haskell packages
Many Haskell libraries and executables are grouped in packages. They are all available on Hackage, and a subset of them is curated on Stackage. To install and manage these packages, several methods are available:
See Haskell package guidelines for more information on creating new Haskell packages.
Pros/Cons of the different methods
The following table documents the advantages and disadvantages of different package management styles.
|Official repositories||Provided by ArchLinux developers, consistent versions of packages, already compiled||Only a few packages available, only dynamic libraries available|
|cabal-install||All packages available, root not required||Installed in home directory, failures in dependency resolution, difficult to remove specific packages|
|stack||All packages available (favors Stackage), root not required||Installed in home directory, versions are pinned to snapshot, difficult to remove specific packages|
|Arch User Repository||Simple to get started||Risk of unmaintained or orphaned packages, incompatible versions of packages possible|
cabal-installis the package that contains the "cabal" command-line utility, whereas
Cabalis the package that provides the "Cabal" library, used by both cabal-install and stack.
Preparation and $PATH
To run user-wide executables installed by cabal-install,
~/.cabal/bin must be added to the
$PATH variable. That can be done by putting the following line in your shell configuration file, for instance
~/.bashrc for or
~/.zshrc for :
Installing packages user-wide
$ cabal update $ # Dynamic linking $ cabal install --disable-library-vanilla --enable-shared --enable-executable-dynamic <pkg> $ # Static linking (requires ghc-static and ghc-pristine) $ cabal install --with-compiler=/usr/share/ghc-pristine/bin/ghc <pkg>
It is possible to install a package system-wide with the
--global flag, but this is strongly discouraged. With the user-wide install, all files are kept in
~/.cabal and libraries are registered to
~/.ghc, offering the possibility to do a clean-up easily by simply removing these folders. With system-wide install, the files will be dispersed in the file system and difficult to manage.
Cabal sandboxes provide a consistent local package database and environment (similar to virtual-env in Python or rvm in Ruby). To create a sandbox in the current directory, run:
cabal sandbox init
It can be later removed using
cabal sandbox delete
By default, if the current directory contains a sandbox, cabal will take advantage of it for installation, so you can follow the same steps as #Installing packages user-wide. If you want to use a sandbox elsewhere, you can – while the current directory contains the sandbox – run
cabal exec "$SHELL" to start a sandbox-aware shell. Then you can change the directory to wherever you want, and cabal will still use the sandbox. Alternatively, you can pass the
--sandbox-config-file=/somewhere/cabal.sandbox.config flag to cabal.
To run executables within a cabal sandbox, you must also set
or start a local shell with
cabal exec "$SHELL".
There is no easy way to do it. Cabal does not have support for this functionality.
Consider installing to a sandbox instead, which can be deleted without affecting other sandboxes or your user-wide installation.
One thing to make your life easier is use zsh auto completion to find all the Haskell packages.
If you want/can fix/reinstall whole user-wide Haskell package system - remove
~/.ghc and start from scratch. This is often necessary when GHC is upgraded.
Stack is a build tool that focuses on automatically curated, consistent package sets rather than dependency resolution. This means it's easy to install a set of packages without concern of version conflicts as long as they coexist within a given Stackage snapshot. It can be installed through either , AUR or AUR. The latter provides statically linked binaries, thereby avoiding dozens of
haskell-* dependencies. More information can be found at § Install/upgrade # Arch Linux.
In default config,
stack trades disk space off for build stability. One can easily get
~/.stack in tens of GiB — because stack will download multiple GHC versions, snapshots and whatnot, and will never clean up anything.
The GHC version bloat can be mitigated by this snippet in
# stop downloading GHCs into ~/.stack install-ghc: false # allow stack to pick the system ghc (false by default) system-ghc: true # allow e.g. GHC 8.8.3 from Arch with Stack Snapshot 8.8.2 compiler-check: newer-minor # fix "there are files missing" ghc compile errors ghc-options: "$everything": -dynamic # Ref: https://docs.haskellstack.org/en/stable/yaml_configuration/#system-ghc
stack path --compiler-exe can be used to test whether stack picks
/usr/bin/ghc-n.n.n (i.e. the config works) or something else.
With this config, installing haskell-ide-engine from source will produce "mere" 1.9 GiB
~/.stack. You cannot wipe it now; as
ldd $(which hie) shows, roughly half of the 250 libs that
~/.local/bin/hie links to come from
Using dynamic linking will be easier on your disk and RAM (by sharing pages between multiple running haskell programs), and will free you from troubleshooting cross-ghc mixing errors. But it has its own disadvantage: all tools you install from source will break on every update of
haskell-* Pacman packages. You'll see
libHS... => not found in
ldd output in this cases; or when running broken binary, the usual
error while loading shared libraries: libHSfoobar-...-ghc8.8.3.so: cannot open shared object file: No such file or directory error. To fix this, just rebuild and reinstall the broken tool (to relink it to newer libraries).
Arguably, this "disadvantage" is a feature when updating often: it provides a clear, trivial to diagnose, failure path, when dependencies move away from under dependees. Compare to static linking: tools you built will continue containing stale dependency code, and appear to continue to work — except sometimes, will break, in chaotic and unpredictable ways.
ghcup makes it easy to install specific versions of ghc and can also bootstrap a fresh Haskell developer environment from scratch. It follows the UNIX philosophy of do one thing and do it well. Similar in scope to rustup, pyenv and jenv.