Creating a New Stack Project
We create a new Stack project using stack new
. This creates a package. We
need to pass the package name as an argument to stack new
. Package names can
be composed of letters, dashes, and numbers. It is common practice, especially
for packages published on Hackage to have lowercase names, with words in
multi-word names separated by dashes. Let's create a hello-world
package:
$ stack new hello-world
This creates a new directory hello-world
containing the source code of the
package we are about to implement. Let's inspect the contents of this directory:
$ tree hello-world
hello-world
├── CHANGELOG.md
├── LICENSE
├── README.md
├── Setup.hs
├── app
│ └── Main.hs
├── hello-world.cabal
├── package.yaml
├── src
│ └── Lib.hs
├── stack.yaml
└── test
└── Spec.hs
3 directories, 10 files
Here's what these files are:
General Information
CHANGELOG.md
is a Markdown file that contains the list of changes made to our project between different package versions.LICENSE
states the license under which we are making our package available to others if we publish it on Hackage or Github.README.md
should contain a package description. In particular, this is the description others will read when they visit the webpage corresponding to our package on Hackage. Again, this is a Markdown file.
Since we won't publish our projects on Hackage in this course, we will ignore these files. You can even delete them if you want.
Cabal Files
GHC's build and package management system is called Cabal. For the longest time,
Haskell users used Cabal to manually install packages that their projects
dependend on, and then they could build their own projects using GHC. This often
led to clashes when different projects depended on different versions of the
same package. Stack solves this problem by creating a sandbox for every project.
This sandbox contains the packages that this project depends on. This sandbox is
separate from the sandboxes of other projects, so these clashes are avoided.
Under the hood, Stack still uses Cabal to manage packages and build projects. It
only instructs Cabal and GHC to install and look for packages in a
project-specific location. Since Stack uses Cabal, our project needs to contain
the files that Cabal uses to build our project. Those are Setup.hs
and
hello-world.cabal
.
Even when programming serious Haskell projects, you'll rarely have to touch
these files. In fact, hello-world.cabal
is automatically generated from
package.yaml
, which contains our package's configuration. Setup.hs
controls
the inner workings of the build process using Cabal.
Stack Project Configuration Files
Our Stack project is configured using two files package.yaml
and stack.yaml
.
package.yaml
contains the description of our project. This includes our
package's name, version number, author, the list of other packages that our
package depends on, the list of executables to build from the source code,
compiler options, etc. We'll talk about this in greater detail shortly.
stack.yaml
contains configuration options of Stack itself that are necessary
to build our project. This part is important when building projects on
Timberlea. So **it is imperative that you read the
section on stack.yaml
.
Library Files, Application Source Code, and Tests
Every Stack project is treated as a library that provides modules to be imported
by other projects. These files are contained in the src
directory by default,
but we can change this by editing package.yaml
, as discussed shortly. In the
skeleton created by stack new
, the src
directory contains the file Lib.hs
.
We usually end up deleting or renaming this file so our modules have names that
describe their purpose.
When creating a project using stack new
, Stack creates a skeleton for our
project that is setup to build an executable, a program we can run. By default,
the source code files specific to this executable and which are not to be made
available to other packages are in the app
directory. Again, this can be
changed. stack new
puts a Main.hs
file into this directory. I recommend to
leave this name as it is because this tells the reader of our code that this is
the entry point of our progam. This is especially important if we add other
modules to the app
directory.
The final directory is test
, which contains code to test our library.
stack new
places a single test file Spec.hs
into this directory. A bigger
project will probably contain a number of test files in this directory. These
tests can be run using stack test
.
For our projects in this course, we will not write any tests, so you can ignore
this directory or even delete it. If you delete it, you need to remove the
corresponding section from package.yaml
(discussed shortly).