Files
haskell.nix/docs/tutorials/getting-started.md
T
Hamish Mackenzie 9e6820cc71 Add haskell-nix.project (and project') (#703)
Generalized version of the `cabalProject` and `stackProject`
functions.

Automatically selects the correct project type based on the
`projectFileName` argument if provided or what files exist in
the `src` directory if no `projectFileName` was specified.

If it cannot be determined which it should use the following
error message is given:

```
error: haskell-nix.project : both `stack.yaml` and `cabal.project` files exist set `projectFileName = "stack.yaml;"` or `projectFileName = "cabal.project";`
```
2020-06-19 20:07:19 +12:00

4.6 KiB

Getting started

haskell.nix can automatically translate your Cabal or Stack project and its dependencies into Nix code.

This tutorial will teach you how to setup your project

Assuming you have Nix installed, you can start setting up your project.

Setting up the Cachix binary cache

You can avoid compiling GHC and nix-tools by configuring Cachix so you can benefit from the binary cache built by CI:

$ nix-env -iA cachix -f https://cachix.org/api/v1/install
$ cachix use iohk

Scaffolding

The following work with stack.yaml and cabal.project based projects.

Add default.nix:

{ # Default version of GHC to use (when not otherwise specified)
  defaultCompilerNixName ? "ghc865"

# Fetch the latest haskell.nix and import its default.nix
, haskellNix ? import (builtins.fetchTarball https://github.com/input-output-hk/haskell.nix/archive/master.tar.gz) {
  inherit defaultCompilerNixName;
}

# haskell.nix provides access to the nixpkgs pins which are used by our CI, hence
# you will be more likely to get cache hits when using these.
# But you can also just use your own, e.g. '<nixpkgs>'
, nixpkgsSrc ? haskellNix.sources.nixpkgs-2003

# haskell.nix provides some arguments to be passed to nixpkgs, including some patches
# and also the haskell.nix functionality itself as an overlay.
, nixpkgsArgs ? haskellNix.nixpkgsArgs

# import nixpkgs with overlays
, pkgs ? import nixpkgsSrc nixpkgsArgs
}: pkgs.haskell-nix.project {
  # 'cleanGit' cleans a source directory based on the files known by git
  src = pkgs.haskell-nix.haskellLib.cleanGit {
    name = "haskell-nix-project";
    src = ./.;
  };
}

Or a shorter default.nix that uses the default nixpkgs and default GHC:

{ haskellNix ? import (builtins.fetchTarball https://github.com/input-output-hk/haskell.nix/archive/master.tar.gz) {}
, pkgs ? haskellNix.pkgs
}: pkgs.haskell-nix.project {
  src = pkgs.haskell-nix.haskellLib.cleanGit {
    name = "haskell-nix-project";
    src = ./.;
  };
}

!!! note "git dependencies" If you have git dependencies in your project, you'll need to calculate sha256 hashes for them.

Working with a project

Top-level attributes are Haskell packages (incl. dependencies) part of your project.

To build the library component of a package in the project run:

nix-build -A your-package-name.components.library

There are also other components such as exes, tests, benchmarks and all. To build an executable:

nix-build -A your-package-name.components.exes.your-exe-name

To open a shell for use with cabal run:

nix-shell -A shellFor
cabal new-repl your-package-name:library:your-package-name
cabal new-build your-package-name

To open a shell for use with stack see the following issue.

Pinning the Haskell.nix version

For simplicity's sake we will use fetchTarball for the examples in this documentation. This will always get the latest version, and is similar to an auto-updating Nix channel.

However, in your own project, you may wish to pin Haskell.nix (as you would pin Nixpkgs). This will make your builds reproducible, more predictable, and faster (because the fixed version is cached).

One way of doing this is to use nix-prefetch-git to get a JSON file with a revision and SHA-256 hash of Haskell.nix.

$ nix-prefetch-git --quiet https://github.com/input-output-hk/haskell.nix | tee haskell-nix-src.json
{
  "url": "https://github.com/input-output-hk/haskell.nix",
  "rev": "f1a94a4c82a2ab999a67c3b84269da78d89f0075",
  "date": "2019-06-05T01:06:12+00:00",
  "sha256": "0ggxsppjlb6q6a83y12cwgrdnqnw1s128rpibgzs5p1966bdfqla",
  "fetchSubmodules": false
}

(The tee command is just to show you the result.) Use the following expression to import that version:

{ nixpkgs ? <nixpkgs> }:

let
  spec = builtins.fromJSON (builtins.readFile ./haskell-nix-src.json);
  haskell-nix-src = (import nixpkgs {}).fetchgit {
    name = "haskell-lib";
    inherit (spec) url rev sha256 fetchSubmodules;
  };
in
  import nixpkgs (import haskell-nix-src)

There are other possible schemes for pinning. See haskell.nix/lib/fetch-external.nix, the niv tool, or the Nix Flakes proposal.

Going forward

There are a number of things to explore further in the tutorials section.