Haskell

Related articles
Haskell package guidelines
List of programming languages
From
Wikipedia
:
it is a general-purpose, statically typed, purely functional programming language with type inference and lazy evaluation;
it has pioneered type classes, which enable type-safe operator overloading.
Installation
There are several choices for
Haskell
installation. One is supported by Arch Linux, while others are officially supported by Haskell for any Linux distribution.
Since version
8.0.2-1
, the Arch
ghc
package and all
haskell-*
packages in
extra
provide only dynamically linked libraries.
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. For this reason using
pacman
and the
official repositories
is preferred for managing end-user applications. But it has its own disadvantage:
all tools you install from source will break
on every update of
ghc
,
ghc-libs
or
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.
Note
For a detailed explanation of why Arch moved to dynamic linking for Haskell packages, see this
maintainer's response
.
On the other hand, static linking is generally easier to maintain, does not force you to rebuild all tools from source after every update of their dependencies and is currently better supported by the GHC. For these reasons, static linking is the preferred and recommended option for local development. Otherwise, if you want dynamic linking, to link successfully one must configure GHC, Cabal and Stack for this, as the default is to use static linking.
To install Haskell from Arch
official repositories
using
pacman
, continue reading
#Native installation
. Note that this might install several hundred
haskell-*
packages into your system.
Otherwise, skip to the section
#Alternate installations
.
If you wish to use
ghc
(from the
official repositories
) with static linking, it is possible, but is more complex to setup, see
#Static linking
.
Native installation
To use Haskell,
install
the following packages:
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-install
or
stack
— Build tools that rely on GHC to compile Haskell sources.
Cabal
is the classic build tool focused on dependency resolution and source packages from
Hackage
(Haskell community's central package archive of open source software).
Stack
is another build tool focused on curated snapshots and source packages from
Stackage
(a stable subset of Hackage that provides curated sets (snapshots) of packages known to work well with each other).
Tip
Both Cabal and Stack are stable and mature build tools. Many Haskell developers use Cabal, while many others prefer Stack. If you are not sure which tool to choose, try to install both and see which one works best for you.
Configuration
Note
You can skip this section if you are not going to compile Haskell from source, and just use Haskell applications distributed in the repositories.
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.hs
main = putStrLn "Hello, World"
Compile and run it with:
$ ghc -dynamic Main.hs
$ ./Main
Hello, World
Configuring Cabal for dynamic linking
First, run the following command to download the latest list of packages from Hackage and create global configuration file
~/.config/cabal/config
(or the file
$CABAL_CONFIG
points to):
$ cabal update
Tip
It is advisable to periodically run
cabal update
to 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
~/.config/cabal/config
:
~/.config/cabal/config
library-vanilla: False
shared: True
executable-dynamic: True
program-default-options
  ghc-options: -dynamic
library-vanilla: False
suppresses the creation of static libraries (if your project contains a library).
shared: True
enables the creation of shared libraries (if your project contains a library).
executable-dynamic: True
causes dynamic linking to be used for executables (if your project contains executables).
ghc-options: -dynamic
adds the
-dynamic
flag to every invocation of GHC (e.g. if a package has a non-trivial
Setup.hs
).
Configuring Stack for dynamic linking
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
--system-ghc
and
--resolver
flags:
$ 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
--resolver nightly-2020-09-01
.
Stackage typically lags behind new GHC releases. It may happen that no Stackage snapshot for your system GHC has yet been released. In this case you might want to choose a snapshot for some earlier minor version of GHC or temporarily downgrade your Haskell installation and wait until support for newer GHC releases finally lands on Stackage.
To configure Stack for dynamic linking, add the following snippet:
~/.stack/config.yaml
# 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, Stackage 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
Package management
Most of Haskell libraries and executables are distributed in units of source packages available from Hackage and Stackage. Repositories used by Cabal and Stack respectively.
GHC, the standard compiler for Haskell, generates machine code that can be run natively on Linux. As is common in other compiled languages, a number of popular Haskell packages are available from official Arch repositories in pre-built form.
Some additional packages can be installed from
AUR
. This packages may need to build from source, building
AUR
packages or developing software require a compiler and build tools to be installed. Using the
#Native installation
method is discouraged for this use case, instead see
#Alternate installations
.
Therefore there are four main sources for Haskell packages: Hackage (Cabal), Stackage (Stack),
official repositories
and
AUR
.
The following table summarizes the advantages and disadvantages of different package management styles.
Method
Pros
Cons
Official repositories
Easier package management using
pacman
Already compiled dynamically linked
Not all packages available
Makes difficult compiling from source
Cabal
All packages available
Root not required
Better support for development
Installed in home directory
Difficult to remove specific packages
Stack
All packages available (favors Stackage)
Root not required
Better support for development
Installed in home directory
Versions are pinned to snapshot
Difficult to remove specific packages
AUR
Additional packages available
Risk of unmaintained or orphaned packages
Incompatible versions of packages possible
Cabal
Note
In Haskell, the term
Cabal
can refer to either:
Cabal file format that describes Haskell packages and their dependencies;
Cabal library that works with Cabal file format;
cabal
command-line tool (provided by
cabal-install
) that uses Cabal library to build Haskell packages.
In the context of this article,
Cabal
usually means
cabal
command-line tool unless specified otherwise.
Cabal is "the original" build system for Haskell. Most of libraries and tools you can find on Hackage can be installed via Cabal.
Installing packages
To run user-wide executables installed by Cabal,
~/.cabal/bin
must be added to the
$PATH
environment variable
.
export PATH="$HOME/.cabal/bin:$PATH"
Run the following command to install a Hackage package and all of its dependencies in a single step:
$ cabal install
package
Warning
If you are using
cabal
from the
official repositories
, as of December 2024 Cabal
ignores
ghc-options
from
~/.config/cabal/config
while building packages with
build-type: Custom
. Therefore, it is necessary to specify
--ghc-options=-dynamic
flag on the command line  otherwise you might experience build errors.
You can also build and install a Haskell package from source. To do this, run
cabal install
without specifying any package in the directory with the sources.
Each Cabal package should specify a list of its dependencies and their version constraints in the
.cabal
file according to the
Package Versioning Policy
(PVP). During the package installation, Cabal tries to find a set of dependencies that satisfies all the constraints. This process is called
dependency resolution
.
There are reasons why Stack exists; Cabal is known to generate a lot of friction with beginners, although it has been getting better in the past years. Most of the time dependency resolution works well but sometimes it fails. In this case you will need to figure out the cause of the problem and give Cabal some hints about how to resolve offending dependencies. For example, sometimes it is necessary to add
--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 one had to use both
--allow-newer
and
--constraint='haskeline < 0.8.0.0'
command-line flags to get a successful compile.
Removing packages
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
.
To reinstall the entire user-wide Haskell package system, remove
~/.cabal
and
~/.ghc
and start from scratch. This is often necessary when GHC is upgraded.
For more precision, it is possible to use
ghc-pkg unregister
package
or
ghc-pkg hide
package
/
ghc-pkg expose
package
directly on the
user package database
— this makes GHC "forget" about an installed package (or pretend it is not there). However neither of these removes any files.
Stack
Stack is another tool to manage Haskell packages. It has slightly different goals than Cabal, with a slightly different philosophy. It uses Cabal library under the hood and integrates with Hackage — but maintains its own repositories of packages (snapshots) on Stackage with the promise that snapshots are curated and include packages which work well together.
Installing packages
In its default configuration, Stack installs compiled executables to
~/.local/bin
. Add this directory to the
$PATH
environment variable
, ideally via your
shell configuration file
:
export PATH="$HOME/.local/bin:$PATH"
Run the following command to download, build and install a Stackage package:
$ stack install
package
Warning
As of December 2024 Stack
ignores
ghc-options
from
~/.stack/config.yaml
while building
Setup.hs
. If you experience build errors in
Setup.hs
like
Could not find module ‘Prelude’ There are files missing in the ‘base-...’ package
, try to install
ghc-static
package as a workaround.
You can also build and install a Haskell package from source by running the following command from the package directory:
$ stack install --resolver
resolver
Note that you should specify the same resolver as one used for
stack setup
command.
Removing packages
Stack does not support the "uninstall" operation.
If you want to reinstall the entire user-wide Haskell package system, remove
~/.stack
directory and start from scratch. This is often necessary when GHC is upgraded.
Development tools
Tools
haskell-language-server
haskell-language-server
is a
Language Server Protocol
(LSP) implementation for Haskell. It provides IDE-like features such as code completion, "goto definition", documentation on hover, linting, formatting or refactoring for any editor integrating with the LSP.
If you are using dynamically linked Haskell packages from
pacman
, install
haskell-language-server
. Otherwise, if you prefer static linking, install
haskell-language-server-static
AUR
. This package contains statically linked binaries for each supported version of GHC. Alternatively, haskell-language-server can be installed via
ghcup
or by the
Haskell extension
for
Visual Studio Code
.
haskell-language-server will attempt to automatically determine the build configuration when you open your project. If automatic detection fails, you might want to
configure it manually
using a
hie.yaml
file in the project root directory.
ghcid
ghcid
is a
GHCi
-based tool for Haskell development that provides simple and robust way to display compiler errors and warnings on every source code change. It can be installed via
ghcid
AUR
package.
hoogle
hoogle
allows you to search the Haskell libraries by either function name, or by approximate type signature. It can be installed via
hoogle
package.
An online version of hoogle is available at
https://hoogle.haskell.org
.
Linters
hlint
hlint
suggests possible improvements to Haskell code such as using alternative functions, simplifying code and spotting redundancies. It is available through
hlint
package.
stan
stan
is a Haskell static analyzer, complementary to
hlint
. It is in the beta phase as of December 2025. Available in
haskell-stan
AUR
.
weeder
weeder
is an application to perform whole-program dead-code analysis.
Formatters
Floskell
— Fork of hindent focusing on flexibility and configurability.
https://github.com/ennocramer/floskell
||
haskell-floskell
Fourmolu
— Fork of Ormolu that adds an ability to configure various formatting parameters.
https://github.com/parsonsmatt/fourmolu
||
haskell-fourmolu
hindent
— Extensible Haskell pretty printer.
https://github.com/mihaimaruseac/hindent
||
hindent
Ormolu
— Formatter for Haskell source code, implementing one "true" formatting style which admits no configuration.
https://github.com/tweag/ormolu
||
haskell-ormolu
stylish-haskell
— Simple Haskell code prettifier.
https://github.com/jaspervdj/stylish-haskell
||
stylish-haskell
Editors
Visual Studio Code
Visual Studio Code
has a
Haskell extension
powered by
haskell-language-server
. If you do not have haskell-language-server installed, the Haskell extension will automatically download and install statically linked Linux binaries for you.
IntelliJ IDEA
IntelliJ IDEA
support for Haskell is provided by the
Haskell LSP plugin
. It works with any edition of IntelliJ IDEA including
intellij-idea-community-edition
.
You will need to install Stack in order to create a new project or import an existing one into IntelliJ IDEA. As of June 2021 Cabal-only projects
are not supported
.
Vim
Basic syntax highlighting and indentation for
Vim
can be obtained via the
haskell-vim
plugin. For better IDE-like experience use one of
LSP client
plugins (e.g.
coc.nvim
,
ALE
,
LanguageClient-neovim
) together with
haskell-language-server
.
Emacs
Basic
Emacs
support for Haskell is provided by the official
haskell-mode
. For more advanced features, also use
lsp-haskell
with
haskell-language-server
.
Alternate installations
The methods described in this sections are best suited for Haskell development setups. It is possible to use them along packages from the
official repositories
, if this is the case, make sure you know which version of the Haskell package you are using, if the one installed by
pacman
or by one of the following methods.
ghcup
This is the recommended method for installing Haskell in any Linux distribution. GHCup installs GHC, tools and libraries in your home directory and allows to have multiple versions in parallel and handle them with relative ease. It is similar in scope to
rustup
,
pyenv
and
jenv
.
Install
ghcup-hs-bin
AUR
package. Alternatively, you may follow official
installation instructions
or manually download
ghcup binary
and place it somewhere into your
$PATH
.
By default, ghcup will install executables into
~/.ghcup/bin
. You need to add this directory to the
$PATH
environment variable in your shell configuration file, for instance
~/.bashrc
for
bash
or
~/.zshrc
for
zsh
. If you want to run executables installed by Cabal, add
~/.cabal/bin
to
$PATH
as well:
export PATH="$HOME/.cabal/bin:$HOME/.ghcup/bin:$PATH"
Tip
If you want to use XDG style directories, define the
GHCUP_USE_XDG_DIRS
environment variable (
https://ghcup.readthedocs.io/en/latest/guide/#xdg-support
).
GHCup provides a convenient TUI which supports most of its functionality:
$ ghcup tui
Alternatively, you can use the following CLI commands:
List available versions of GHC and Cabal:
$ ghcup list
Install the recommended version of GHC:
$ ghcup install ghc
You can also install a specific version of GHC, for example:
$ ghcup install ghc
8.10.2
The commands above do not automatically make GHC available on the
$PATH
. You need to select which GHC version to use by default:
$ ghcup set ghc
8.10.2
Note
GHCup is commonly used in combination with Cabal to manage other Haskell packages, you can use it to install Stack see
#Stack
.
Install the recommended version of Cabal:
$ ghcup install cabal
GHCup can install
haskell-language-server
too, use the following command:
$ ghcup install hls
For more information, refer to official
ghcup
and
Cabal
documentation.
Using along native installation
In case you decide to use
GHCup and Cabal
along the native installation you need to specify Cabal which GHC to use specifying the path of the GHC version to use, search for the line
with-compiler:
and uncomment it:
~/.config/cabal/config
with-compiler:
path_of_your_ghc
Remember that the path of your GHC in case of using GHCup is going to be under
~/.ghcup/bin
. Also GHCup, once you set the GHC version you wish, will link that version to
~/.ghcup/bin/ghc
. If you set that path in the Cabal configuration, you can change which version of GHC Cabal uses using GHCup.
Stack
You can install Stack using the
stack-bin
AUR
package or using GHCup (see
#ghcup
). Alternatively, you may follow official
installation instructions
or manually download
Stack binary
and place it somewhere into your
$PATH
.
If you want to run executables installed by Stack, add
~/.local/bin
directory to the
$PATH
, see
Environment variables
for more information on how to do this.
Stack will use an isolated version of GHC, so it does not require any additional configuration. Run
stack setup
to automatically install GHC from the latest Stackage LTS snapshot:
$ stack setup
You can now use Stack to build and install statically linked Haskell packages without any special configuration or command line flags:
$ stack install
package
For more information, refer to official
Stack documentation
.
Nix
This article or section needs expansion.
Reason:
I cannot offer a good enough overview, due to no experience with it (Discuss in
Talk:Haskell
)
A completely different way of installing Haskell is
Nix
package manager. Nix has a steeper learning curve but offers greater flexibility in managing both Haskell and non-Haskell packages in a reliable and reproducible fashion.
Tips and tricks
Static linking
Warning
There is no warranty that it will work correctly, since the GHC version in the repositories is very outdated. You may face with bugs that currently have no solution other than updating GHC
[1]
.
Note
This section explains how to build statically linked Haskell packages on Arch, but still use GHC installed from the official repositories. Before you proceed, make sure to remove
~/.cabal
and
~/.stack
directories if they exist.
In the context of this article, static linking does not mean generating completely static ELF binaries. Only Haskell code will be linked statically into a single ELF binary, which may be dynamically linked to other system libraries such as
glibc
.
To use static linking, one must, at minimum, install the static boot libraries through the
ghc-static
package. This would allow you to build projects that depend exclusively on the boot libraries as well as on any other libraries that are not installed through the
haskell-*
packages from the official repositories.
Unfortunately, if your project depends on any of dynamically linked
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 discovers the static libraries are missing:
Could not find module ‘
SomePackage.SomeModule
’
There are files missing in the ‘
somepackage-0.1.0.0
’ package,
try running 'ghc-pkg check'.
Use -v (or `:set -v` in ghci) to see a list of the files searched for.
Unlike
ghc-static
, there are no "
haskell-*-static
" packages available for linkage. There are other ways to work around this issue though, as described in each of the sections below.
Static global package database
A direct
approach
is offered by the official
ghc-static
package, which exposes an alternative "static" global package database at
/usr/lib/ghc-
version
/static-package.conf.d
. The static database is limited to only the statically linkable boot packages, therefore if Cabal is reconfigured to use the static database instead of the default database, it would behave as though the dynamic-only
haskell-*
packages do not exist.
The precise path of the static database could be determined at build time using a command such as:
$ ghc --print-global-package-db | sed 's/\(package\.conf\.d\)$/static-\1/'
/usr/lib/ghc-
version
/static-package.conf.d
Here is how to enable the static database for use:
When building packages with Cabal, one can pass the following flag to limit the selection of global packages to only the boot packages:
$ cabal configure --ghc-pkg-option="--global-package-db=$(ghc --print-global-package-db | sed 's/\(package\.conf\.d\)$/static-\1/')"
When building directly using GHC rather than Cabal, one can pass the following flags to override the global package database:
$ ghc -clear-package-db -package-db "$(ghc --print-global-package-db | sed 's/\(package\.conf\.d\)$/static-\1/')" -user-package-db ...
ghc-pristine
Install
ghc-pristine
AUR
package, which wraps over an existing GHC installation to create a separate GHC distribution in
/usr/share/ghc-pristine
, with a package database that contains only boot libraries. This effectively creates a semi-isolated environment without dynamically linked
haskell-*
packages, but still makes use of the GHC compiler from the official repositories. 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 in
~/.config/cabal/config
:
~/.config/cabal/config
with-compiler: /usr/share/ghc-pristine/bin/ghc
You can also specify the path to the compiler on a per-project basis by running the following command from the project directory:
$ cabal configure --with-compiler=/usr/share/ghc-pristine/bin/ghc
stack-static
Install
stack-bin
AUR
package. Similarly to
cabal-static
method, make sure that the only other Haskell packages you have installed from the official repositories are
ghc
,
ghc-libs
and
ghc-static
. Then setup Stack to use system GHC as explained in
#Configuring Stack for dynamic linking
:
$ stack setup --system-ghc --resolver
resolver
To make these options permanent, paste the following snippet to
~/.stack/config.yaml
:
~/.stack/config.yaml
# 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, Stackage snapshot for GHC 8.8.2 with system GHC 8.8.3.
compiler-check: newer-minor
This configuration will allow you to build statically linked packages as you would normally do, but using system GHC installation instead of GHC provided by Stack.
hpack-static-bin
hpack-static-bin
AUR
provides a statically linked (meaning no
haskell-*
dependencies) alternative to
haskell-hpack
. It is precompiled, so no make dependencies are needed.
See also
Haskell documentation
Haskell Wiki
GHC User Guide
Cabal User Guide
Stack User Guide
Haskell community's central package archive
Stable source of Haskell packages
Haskell API search engine
Learn You a Haskell for Great Good!
Real World Haskell
Haskell Wikibook
What I Wish I Knew When Learning Haskell
Awesome Haskell: an auxiliary list of awesome Haskell links, frameworks, libraries and software