93 lines
2.5 KiB
Markdown
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
|
|
```
|