nix-playgraound/notes/007-haskell.md
Hassan Abedi abb13bce10 WIP
2026-04-21 16:51:32 +02:00

93 lines
2.5 KiB
Markdown

# Haskell Project
This note covers `05-haskell/`, which packages a tiny Cabal library and executable with Nix, runs a Cabal test suite during `nix flake check`, and
provides a dev shell for editing it.
---
## 1. What the Example Teaches
The example combines three pieces that show up in real Haskell projects:
- a local Cabal package, defined by `mini-haskell.cabal`,
- a small library module under `src/`,
- an executable under `app/`, and
- a test suite under `test/`,
- a flake output that builds that package with `callCabal2nix`, and
- a dev shell that provides GHC, `cabal-install`, and Haskell Language Server.
That keeps the example focused on one idea: a flake can describe a small Haskell project end to end, including code, tests, and a development
environment.
---
## 2. The Package Build
`pkgs.haskellPackages.callCabal2nix` reads the local Cabal file and produces a Nix derivation for the package:
```nix
project = haskellPackages.callCabal2nix "mini-haskell" ./. { };
```
The first argument is the package name as it should appear in Nix. The second is the source tree. The third is an attrset of overrides, which this
example leaves empty.
In this example, the Cabal package contains:
- a library module, `MiniHaskell.Greeting`,
- an executable that imports that library, and
- a test suite that imports the same library.
That derivation becomes `packages.<system>.default`, so `nix build` produces the executable, and `nix run` executes it.
---
## 3. The Dev Shell
The dev shell uses `pkgs.mkShell` and adds the tools you need to edit and run the project:
- `ghc` for the compiler,
- `cabal-install` for local development commands, and
- `haskell-language-server` for editor support.
This keeps the shell small and obvious. For projects with many Haskell dependencies, `shellFor` can construct a shell from the package set itself, but
this example stays with `mkShell` to keep the mechanics visible.
---
## 4. The Test Suite Check
The flake defines a second derivation for checking:
```nix
checkedProject = pkgs.haskell.lib.doCheck project;
checks.${system}.test-suite = checkedProject;
```
`doCheck` tells the Haskell package build to run the Cabal test suite. That gives `nix flake check` one concrete behavior to verify:
- the Cabal package evaluates,
- the library and executable build, and
- the test suite passes.
---
## 5. Commands to Try
```bash
cd 05-haskell
nix develop
cabal run
cabal run -- flakes
cabal test
nix build
./result/bin/mini-haskell
./result/bin/mini-haskell flakes
nix run
nix run . -- flakes
nix flake check
```