- Haskell is a general-purpose, statically typed, purely functional programming language with type inference and lazy evaluation. Developed to be suitable for teaching, research and industrial application, Haskell has pioneered a number of advanced programming language features such as type classes, which enable type-safe operator overloading. Haskell's main implementation is the Glasgow Haskell Compiler (GHC). It is named after logician Haskell Curry.
- 1 Installation
- 2 Configuration
- 3 Managing Haskell packages
- 4 Alternate installations
- 5 Tips and tricks
- 6 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 official repositories. On the other side, building AUR packages or developing software require a compiler and build tools to be installed.or provided in the
To install the latest version of Haskell, install the following packages from the official repositories:
- GHC) — A Haskell compiler. There are several implementations available, but the one used most (which is now de facto the reference) is the GHC (Glasgow Haskell Compiler). (
- Cabal) — A build tool focused on dependency resolution and sources packages from Hackage. Hackage is the Haskell community's central package archive of open source software. (
- Stack) — A build tool focused on curated snapshots and sources packages from Stackage. Stackage is a stable subset of Hackage that provides curated sets (snapshots) of packages known to work well with each other. Alternatively, Stack can be installed through AUR package. It provides statically linked binaries, thereby avoiding dozens of
You can install and configure either Cabal or Stack or both of them. Most of the popular Haskell packages support both Cabal and Stack.
Since version 8.0.2-1, the Arch package and all haskell-* packages in community provide only dynamically linked libraries. Therefore, to link successfully one must configure GHC, Cabal and Stack for dynamic linking, as the default is to use static linking.
Using dynamic linking typically results in faster builds and smaller disk and RAM usage (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-* packages since libraries compiled with GHC do not provide a stable ABI. When running such broken binary, you will see the usual message
error while loading shared libraries: libHS...so: cannot open shared object file: No such file or directory. To fix this, just rebuild and reinstall the broken tool in order to relink it to newer libraries.
On the other hand, static linking is generally easier to maintain and does not force you to rebuild all tools from source after every update of their dependencies. For these reasons, static linking is often the preferred option for local development outside of the package system. If you prefer static linking, see #Static linking or #Alternate installations for details.
Invoking GHC directly
In order to link successfully one must pass the
-dynamic flag to GHC. You can try it with the following file:
main = putStrLn "Hello, World"
Compile and run it with:
$ ghc -dynamic Main.hs $ ./Main
First, run the following command to download the latest list of packages from Hackage and create global configuration file
~/.cabal/config (or the file
$CABAL_CONFIG points to):
$ cabal update
cabal updateto synchronize your local list of packages and dependencies with the newest version on Hackage.
To configure Cabal for dynamic linking, uncomment and edit the following options in
library-vanilla: False shared: True executable-dynamic: True program-default-options ghc-options: -dynamic
library-vanilla: Falsesuppresses the creation of static libraries (if your project contains a library).
shared: Trueenables the creation of shared libraries (if your project contains a library).
executable-dynamic: Truecauses dynamic linking to be used for executables (if your project contains executables).
ghc-options: -dynamicadds the
-dynamicflag to every invocation of GHC (e.g. if a package has a non-trivial
You can use
stack setup command to initialize Stack and create global configuration file
~/.stack/config.yaml. By default Stack will automatically download its own version of GHC to an isolated location upon first invocation. To force Stack to use system GHC installation instead, run
stack setup with
$ stack setup --system-ghc --resolver resolver
Note that you need to specify a resolver which is compatible with your system GHC. Otherwise Stack will happily ignore
--system-ghc flag and download its own copy of GHC. You can determine the version of system GHC using
ghc --version command:
$ ghc --version
The Glorious Glasgow Haskell Compilation System, version 8.10.2
Then visit Stackage website and pick a suitable Long Term Support (LTS) or nightly snapshot matching your system GHC version. Use the selected snapshot for
--resolver flag on the command line, e.g.
--resolver lts-16.15 or
To configure Stack for dynamic linking, add the following snippet to
# Stop downloading GHCs into isolated locations under ~/.stack. install-ghc: false # Allow Stack to pick the system GHC (false by default). system-ghc: true # Allow to use, say, Stack snapshot for GHC 8.8.2 with system GHC 8.8.3. compiler-check: newer-minor # Add the -dynamic flag to every invocation of GHC. ghc-options: "$everything": -dynamic
Managing 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|
Although it's recommended to use Pacman to install GHC, libraries and tools for it from official Arch repositories — at some point you may want to compile your own (or somebody else's) Haskell package from source. Cabal is the first thing you should know about when doing that.
Haskell's Cabal is actually a library; the CLI tool
cabal is better known as . That's how it gets self-updated:
cabal install cabal-install. (Doing so is only necessary when cabal-install version in Arch repos is too old — which is, rarely, if at all.)
Cabal is "the original" build system for Haskell. Most of libraries and tools you can find on Hackage can be installed with
cabal install <package>.
There are reasons why Stack exists; Cabal is known to generate a lot of friction with beginners. For example, sometimes it's necessary to say
cabal install <package> --allow-newer to allow Cabal to ignore
<package>'s PVP-dictated upper bounds on dependency versions, effectively installing
<package> with newer dependencies than the package author has permitted. It gets hairier for less-well maintained packages; for another example, see this thread about installing Idris (another programming language, written in Haskell), where we had to use
cabal install --allow-newer --constraint='haskeline < 0.8.0.0' idris to get a successful compile.
snapshots) with the promise that snapshots are curated and include packages which work well together.is another tool to manage Haskell packages. It pursuits slightly different goals than Cabal, with a slightly different philosophy. It integrates with Hackage — but maintains their own repositories of packages (
Stack will download specific GHC versions and put them into
~/.stack. The default configuration of Stack does not allow it to use
/usr/bin/ghc — you have to pass
--system-ghc to allow.
This will not work with
--system-ghc, unless you install . See below to reconfigure it for dynamic linking.
It seems that many Haskell developers appreciate Nix and use it in their projects.
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, but there are external tools like cabal-store-gc.
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.
ghcup makes it easy to install specific versions of ghc and cabal-install and can also bootstrap a fresh Haskell developer environment from scratch. It can be installed through AUR. It follows the UNIX philosophy of do one thing and do it well. Similar in scope to rustup, pyenv and jenv. See the usage section for an overview.
Tips and tricks
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 or the file
$CABAL_CONFIG points to (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 does not 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 will not use them when building packages by default. Also, this
cabal-install will use the installed compiler.
Alternatively, you can also use ghcup to install an already compiled
cabal-install binary and even a specific version of