Skip to content

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:

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

Shell
$ 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).