Getting Started
===============

Installing Cabal
----------------

The easiest and recommended way to install the ``cabal`` command-line tool
on Linux, macOS, FreeBSD or Windows is through `ghcup <https://www.haskell.org/ghcup/>`__.
It installs the “Haskell toolchain”, which includes Cabal,
the Haskell compiler `GHC <https://www.haskell.org/ghc/>`__
and optionally other useful Haskell tools.

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.

Initializing an application
^^^^^^^^^^^^^^^^^^^^^^^^^^^

To initialize a new Haskell application, run

.. code-block:: console

    $ cabal init myapp --non-interactive

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

.. code-block:: console

    $ 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”:

.. code-block:: cabal

    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
    [#boot-packages]_, 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.

    .. code-block:: diff

        - 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 manageable 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:

.. code-block:: haskell

    module Main where

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


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

.. code-block:: console

     $ 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:

.. code-block:: console

    $ 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


Adding dependencies
^^^^^^^^^^^^^^^^^^^

Next we'll add an external dependency to our application. `Hackage
<https://hackage.haskell.org/>`__ is the Haskell community's central `package`
archive of open source software.

In our application, we'll use a package called `haskell-say
<https://hackage.haskell.org/package/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``:

.. code-block:: cabal

   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:

.. code-block:: haskell

   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:

.. code-block:: console

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

Running a single-file Haskell script
------------------------------------

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

.. code-block:: haskell

    #!/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* [#boot-packages]_, like ``base``, may allow single-file
    scripts to run with a wider range of compiler versions.

    .. code-block:: diff

        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:

.. code-block:: console

    $ 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):

.. code-block:: console

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

See more in the documentation for :ref:`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`_.

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
<https://www.haskell.org/documentation/>`__ or read more about packages and
Cabal on the :doc:`What Cabal does <cabal-context>` page.

.. _Cabal-7070: https://errors.haskell.org/messages/Cabal-7070/

.. [#boot-packages] Packages included with the compiler are also called boot
   packages. Each GHC compiler version has accompanying `release notes`_ that
   list these included packages.

.. _release notes: https://downloads.haskell.org/ghc/latest/docs/users_guide/release-notes.html
