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:
How to initialize a Haskell package.
How files are organized inside a package.
How to compile Haskell files and run a resulting executable.
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.