Minimalistic Nix/Haskell Project Structure

Posted on September 4, 2018 under tag(s) Haskell, Nix

Here’s a minimalistic setup to build cabal-based haskell project given that all the necessary dependencies build with at least one nixpkgs version.

Setup

The default.nix file contains all the necessary nix code for two packages called foo and bar. It pins the nixpkgs version:

{ hostPkgs ? import <nixpkgs> {} }:
let
  pkgs =
    let
      pinnedVersion = hostPkgs.lib.importJSON ./nixpkgs-version.json;
      pinnedPkgs = hostPkgs.fetchFromGitHub {
        owner = "NixOS";
        repo = "nixpkgs-channels";
        inherit (pinnedVersion) rev sha256;
      };
    in import pinnedPkgs {};
  hpkgs = pkgs.haskellPackages;
in hpkgs.override {
      overrides = self: super: {
        foo = hpkgs.callCabal2nix "foo" ./foo {};
        bar = hpkgs.callCabal2nix "bar" ./bar {};
      };
    }

The ./foo/ and ./bar/ folders should contain a single cabal file named foo.cabal and bar.cabal.

The shell.nix file exposes a massive dev environment for foo, bar, and hoogle documentation for their dependencies. It can be used to provide the cabal executable and various tools such as ghcid and hlint too:

with (import ./. {});
shellFor {
    packages = p: with p; [ foo bar ];
    withHoogle = true;
    buildInputs = [ cabal-install ghcid hlint ];
  }

Usage

Update the pinning:

nix-prefetch-git https://github.com/nixos/nixpkgs-channels.git \
  refs/heads/nixos-18.03 > nixpkgs-version.json

Build a package:

nix-build -A foo

Get a dev shell with cabal-install and hoogle docs:

nix-shell

Back