Scaffold a Haskell project w/ IDE support + Nix

Update (May 31, 2021): If you use Flakes, try haskell-template.


I create new Haskell libraries and applications using Nix, along with IDE support in VSCode as follows.

First, install nix-thunk (alternatively, you may use niv or flakes).

# Initialize project layout using cabal
mkdir mypkg && cd mypkg
# Note: Pass --lib, --exe or --libandexe as appropriate
nix-shell -p cabal-install -p ghc --run \
  "cabal init --cabal-version=3.0 -m -l BSD3 --lib -p mypkg"

# Add to git
git init && git add . && git commit -m "Initial commit"

# Remove, or update, version constraint on base to match compiler
vim *.cabal  # and remove version constraint on `base`

# Pin nixpkgs, etc
# You might want to pass --rev, using the value from status.nixos.org
nix-thunk create \
  https://github.com/nixos/nixpkgs.git dep/nixpkgs
nix-thunk create \
  https://github.com/hercules-ci/gitignore.nix.git dep/gitignoresrc

# Write template default.nix
cat << EOF > default.nix
{ pkgs ? import ./dep/nixpkgs {} }:
let 
  inherit (import ./dep/gitignoresrc { inherit (pkgs) lib; }) gitignoreSource;
in 
  pkgs.haskellPackages.developPackage {
    name = "mypkg";
    root = gitignoreSource ./.;
    modifier = drv:
      pkgs.haskell.lib.addBuildTools drv (with pkgs.haskellPackages;
        [ cabal-install
          cabal-fmt
          ghcid
          ormolu
          haskell-language-server
        ]);
  }
EOF

# Test your changes
nix-build
nix-shell --run 'cabal-fmt -i *.cabal'  # Formats your cabal file
nix-shell --run 'ghcid -T :main'

# Create .gitignore and commit
echo -e "dist-newstyle\nresult" > .gitignore
git add . && git commit -m "Nixify"

To enable IDE support,

  • Copy .vscode template to ./.vscode (note: settings.json should point to default.nix instead of shell.nix)
  • Add the appropriate hie.yaml
  • Test your configuration by running nix-shell --run haskell-language-server (it should succeed with module-level reports)
  • Open the folder in VSCode and follow the instructions

Other things you might want to do:

Alternatives

Links to this page
#blog