1. Getting Started

1.1. Installing Cabal

The easiest and recommended way to install the cabal command-line tool on Linux, macOS, FreeBSD or Windows is through ghcup. It installs the “Haskell toolchain”, which includes Cabal, the Haskell compiler GHC and optionally other useful Haskell tools.

1.2. Creating a new application

We create a minimal Haskell application to get a quick overview of the cabal command-line tool:

  1. How to initialize a Haskell package.

  2. How files are organized inside a package.

  3. How to compile Haskell files and run a resulting executable.

  4. How to manage external dependencies.

1.2.1. Initializing an application

To initialize a new Haskell application, run

$ cabal init myapp --non-interactive

in a terminal. This generates the following files in a new myapp directory:

$ tree
.
└── myapp
    ├── app
    │   └── Main.hs
    ├── CHANGELOG.md
    └── myapp.cabal

The myapp.cabal file is a package description file, commonly referred to as a “Cabal file”:

cabal-version:      3.0
name:               myapp
version:            0.1.0.0
-- ...

executable myapp
    import:           warnings
    main-is:          Main.hs
    build-depends:    base ^>=4.19.0.0
    hs-source-dirs:   app
    default-language: Haskell2010

Warning

The version bounds on base, a boot library distributed with GHC [1], are tied to the GHC version visible when cabal init is run. If run with a later version of GHC you might see a difference in the version bounds.

- build-depends:    base ^>=4.19.0.0
+ build-depends:    base ^>=4.20.0.0

It contains metadata (package name and version, author name, license, etc.) and sections to define package components. Components can be used to split large codebases into smaller, more managable building blocks. A component can be of one of several types (executable, library, etc.) and describes, among other things, the location of source files and its dependencies. The myapp.cabal file above defines a single component named myapp of the executable type. Inside the executable section, the build-depends field lists the dependencies of this component.

The app/Main.hs file is where your executable’s code lives:

module Main where

main :: IO ()
main = putStrLn "Hello, Haskell!"

To run the executable, switch into the application directory with cd myapp and run

$ cabal run myapp
...
Hello, Haskell!

This command automatically determines if the executable needs to be (re)built before running the executable. With only one executable component in the package, cabal run (without a component name) is smart enough to infer it, so the name can be omitted.

If you just want to build the executable without running it, run:

$ cabal build
Resolving dependencies...
...
Building executable 'myapp' for myapp-0.1.0.0..
[1 of 1] Compiling Main             ( app/Main.hs, /home/.../myapp/dist-newstyle/build/.../myapp-tmp/Main.o )
Linking /home/.../myapp/dist-newstyle/build/.../myapp

1.2.2. Adding dependencies

Next we’ll add an external dependency to our application. Hackage is the Haskell community’s central package archive of open source software.

In our application, we’ll use a package called haskell-say to print text to the terminal with some embellishment.

Tip

If you installed cabal a while ago but haven’t used it recently you may need to update the package index, you can do this by running cabal update.

In our myapp.cabal file, we will update the build-depends field of the executable section to include haskell-say:

executable myapp
    import: warnings
    main-is: Main.hs
    build-depends:
        base ^>=4.19.0.0,
        haskell-say ^>=1.0.0.0
    hs-source-dirs: app
    default-language: Haskell2010

Note

^>=1.0.0.0 means use version 1.0.0.0 of the library or any more recent minor release with the same major version. To put it simply, this means use the latest version of the library that starts with 1.0.

Next we’ll update app/Main.hs to use the HaskellSay library:

module Main where

import HaskellSay (haskellSay)

main :: IO ()
main = haskellSay "Hello, Haskell!"

import HaskellSay (haskellSay) brings the haskellSay function from the module named HaskellSay into scope. The HaskellSay module is defined in the haskell-say package that we added as a dependency above.

Now you can build and re-run your code to see the new output:

$ cabal run myapp
    ________________________________________________________
   /                                                        \
  | Hello, Haskell!                                          |
   \____       _____________________________________________/
        \    /
         \  /
          \/
    _____   _____
    \    \  \    \
     \    \  \    \
      \    \  \    \
       \    \  \    \  \-----------|
        \    \  \    \  \          |
         \    \  \    \  \---------|
         /    /  /     \
        /    /  /       \  \-------|
       /    /  /    ^    \  \      |
      /    /  /    / \    \  \ ----|
     /    /  /    /   \    \
    /____/  /____/     \____\

1.3. Running a single-file Haskell script

Cabal also supports running single-file Haskell scripts like the following file named myscript:

#!/usr/bin/env cabal
{- cabal:
build-depends:
  base,
  haskell-say ^>=1.0.0.0
-}

import HaskellSay (haskellSay)

main :: IO ()
main = haskellSay "Hello, Haskell!"

Note

Widening or dropping version bound constraints on packages included with the compiler [1], like base, may allow single-file scripts to run with a wider range of compiler versions.

build-depends:
-   base ^>=4.19.0.0,
+   base,

The necessary sections of a .cabal file are placed directly into the script as a comment.

The necessary sections of a package description that would otherwise be in a .cabal file are placed directly into the script as a comment.

Use the familiar cabal run command to execute this script:

$ cabal run myscript

On Unix-like systems, a Haskell script starting with #!/usr/bin/env cabal, like the one above, can be run directly after setting the execute permission (+x):

$ chmod +x myscript
$ ./myscript
   ________________________________________________________
  /                                                        \
 | Hello, Haskell!                                          |
  \____        ____________________________________________/
       \ ... /

See more in the documentation for cabal run.

Warning

Single-file scripts cannot also be part of a package, as an executable or listed as a module. Trying to run a module that is included in a package will error with Cabal-7070.

1.4. What Next?

Now that you know how to set up a simple Haskell package using Cabal, check out some of the resources on the Haskell website’s documentation page or read more about packages and Cabal on the What Cabal does page.