Skip to content

Instantly share code, notes, and snippets.

@CMCDragonkai
Last active September 14, 2021 11:49
Show Gist options
  • Star 1 You must be signed in to star a gist
  • Fork 0 You must be signed in to fork a gist
  • Save CMCDragonkai/ea964d723cd21911e1d968f88b3f939d to your computer and use it in GitHub Desktop.
Save CMCDragonkai/ea964d723cd21911e1d968f88b3f939d to your computer and use it in GitHub Desktop.
Creating a new Stack Project in a Nix Shell #haskell

Creating a new Stack Project in a Nix Shell

There are so many different ways of building and maintaining Haskell projects.

I'm going to talk about using nix-shell and stack.

First you want a ~/.stack/config.yaml:

 local-bin-path: /home/USERNAME/.stack/bin
 
 templates:
   params:
    author-name: NAME
    author-email: EMAIL
    copyright: 'Copyright: (c) 2017 NAME'
    github-username: USERNAME

Make sure to replace USERNAME and NAME and EMAIL with your details.

This will make sure that new projects gets these details automatically injected.

Next we create a project folder.

We can call it my-project.

mkdir my-project
touch my-project/shell.nix

We create a shell.nix that looks like:

#!/usr/bin/env nix-shell
{
  pkgs ? import (fetchTarball https://github.com/NixOS/nixpkgs-channels/archive/8b1cf100cd8badad6e1b6d4650b904b88aa870db.tar.gz) {}
}:
  with pkgs;
  haskell.lib.buildStackProject {
    name = "my-project";
    buildInputs = [ ];
    shellHook = ''
      echo 'Entering Environment'
      set -v

      alias stack='\stack --nix'

      set +v
    '';
  }

This will ensure that stack uses the GHC version provided by shell.nix. It will be forced to select an appropriate Stackage snapshot that is compatible.

Here we can start nix-shell and enter into the environment.

From here perform stack new my-project. This creats a new folder called my-project. Copy over all of its contents into the current directory.

cp -rT my-project/my-project my-project
rm -r my-project/my-project

You can now:

cd my-project
stack build
stack exec my-project-exe
stack test
stack ghci
stack ghci --test

Note that don't use stack install within this environment as it will install executables into your ~/.stack profile. There's no way to install things directly into the project folder from the command line. Instead to add dependencies there are 3 choices.

  1. If it's a dependency outside of Haskell (like a system library), use the shell.nix.
  2. If it's a Haskell library that is within the Stackage snapshot selected, use the package.yaml.
  3. If it's a Haskell library that is outside the Stackage snapshot selected, use the package.yaml and stack.yaml.

An interesting issue is when it's a Haskell executable that you want to use. If it's required for the compilation of the project or testing, you might want to put it into the package.yaml. But if it's just a one-off executable such as in the case of hakyll-init where the static site generator just creates new project folders, you can just use shell.nix.

Note that project specific build artifacts are stored in .stack-work. This is automatically hidden by the generated .gitignore file by stack new.

Existing Cabal Projects

If you have an existing Cabal project, you can instead use stack init, which will expect an existing Cabal file.

Sign up for free to join this conversation on GitHub. Already have an account? Sign in to comment