2. The Haskell Package System: overview

This section summarises the vocabulary and main features of the Haskell Package System.

2.1. Packages

A package is the unit of distribution for the Cabal. Its purpose in life, when installed, is to make available some Haskell modules for import by some other Haskell program. However, a package may consist of much more than a bunch of Haskell modules: it may also have C source code and header files, documentation, test cases, auxiliary tools and whatnot.

Each package has:

The first two components can be combined to form a single text string called the package ID, using a hyphen to separate the version from the name, and dots to separate the version components. For example, "hunit-2.3".

2.2. Packages and the Haskell language

A complete Haskell program will consist of one or more modules (including Main) compiled against one or more packages (of which the Prelude is one). These packages are not referred to explicitly in the Haskell source; instead, the packages simply populate the hierarchical space of module names.

Complete programs must obey the following invariant. Consider all the Haskell modules that constitute a complete program: no two modules must have the same module name.

This invariant is conservative. It preserves the existing semantics of Haskell, and is relatively easy to implement. In particular, the the full name of an entity (type, class, function), which is used to determine when two entities are the same, is simply a pair of the module name and the entity name.

The invariant is unsatisfactory, however, because it does not support abstraction at the package level. For example, a module with an internal (hidden, non-exposed) module called Foo cannot be used in the same program as another package with an unrelated internal module also called Foo. Nor can a program use two packages, P and Q, which depend on different versions of the same underlying package R. We considered more sophisticated schemes, in which (for example) the package name, or package ID, is implicitly made part of every module name. But (a) there is a big design space, and (b) it places new requirements on the implementations. Hence a conservative starting point.

2.3. Packages and compilers

We use the term ``compiler'' to mean GHC, Hugs, Nhc98, hbc, etc. (Even though Hugs isn't really a compiler, the term is less clumsy than ``Haskell implementation''.)

The Cabal requires that a conforming Haskell compiler is somewhat package aware. In summary, the requirements are these:

A complete specification of these requirements is given in Section 3.

2.4. Package distributions

A Cabal package can be distributed in several forms:

2.5. The Setup script

The key question is this: how should Angela Author present her Cabal package so that her consumers (Bob, Sam, Willie, etc) can conveniently use it?

Answer: she provides a tree of files, with two specific files in the root directory of the tree:

The Setup script is an interface. It is meant to give a standard look-and-feel to packages for the sake of Joe User, Bob Builder, Peter Packager, Sam Sysadmin, and Rowland RPM, as well as for layered software tools. This interface provides an abstraction layer on top of any implementation that Angela or Marcus prefers.

The Cabal allows a package author to write the setup script in any way she pleases, provided it conforms to the specification of Section 4. However, many Haskell packages consist of little more than a bunch of Haskell modules, and for these the Cabal provides the simple build infrastructure, a Haskell library that does all the work. The simple build infrastructure, which was used for the example in Section 1.2, is described in Section 5.

In principle, the Setup script could be written in any language; so why do we use Haskell?

It is convenient for consumers to execute Setup.lhs directly, thus:
  ./Setup.lhs ...
This can be achieved by starting Setup.lhs with "#! /usr/bin/env runhugs" or "#! /usr/bin/env runghc" . Since it's a literate Haskell script (.lhs file), the Haskell compiler will ignore this line. However, nothing stops a consumer from running the script interactively, or compiling it and running the compiled binary. Any implementation of Haskell should suffice to run the script, provided the implementation has the Cabal libraries installed.