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.
- If it's a dependency outside of Haskell (like a system library), use the
shell.nix
. - If it's a Haskell library that is within the Stackage snapshot selected, use the
package.yaml
. - If it's a Haskell library that is outside the Stackage snapshot selected, use the
package.yaml
andstack.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
.
If you have an existing Cabal project, you can instead use stack init
, which will expect an existing Cabal file.