https://github.com/srid/haskell-multi-nix
A simple demo of Nixifying a multi-package Haskell project
https://github.com/srid/haskell-multi-nix
cabal haskell nix
Last synced: 4 months ago
JSON representation
A simple demo of Nixifying a multi-package Haskell project
- Host: GitHub
- URL: https://github.com/srid/haskell-multi-nix
- Owner: srid
- License: mit
- Created: 2022-10-06T14:28:19.000Z (almost 3 years ago)
- Default Branch: master
- Last Pushed: 2025-03-16T14:59:03.000Z (4 months ago)
- Last Synced: 2025-03-16T15:28:39.999Z (4 months ago)
- Topics: cabal, haskell, nix
- Language: Nix
- Homepage:
- Size: 23.4 KB
- Stars: 16
- Watchers: 2
- Forks: 3
- Open Issues: 0
-
Metadata Files:
- Readme: README.md
- License: LICENSE
Awesome Lists containing this project
README
# haskell-multi-nix
Just a simple demo of Nixifying a *multi-package* Haskell project.
## Packages
This project has two local Haskell packages:
1. `foo`: a Haskell library exporting `Foo.fooFunc`.
2. `bar`: a Haskell executable that depends on `foo`To build the `foo` library:
```sh
nix build .#foo
```To build the `bar` executable:
```sh
nix build
```To run the executable:
```sh
nix run
```## Dev Shell
The Nix development shell (`nix develop`) allows you to run the various `cabal` commands on the local packages.
For example, this will compile and run the main executable:
```sh
nix develop -c cabal -- run bar
```### ghcid
Using [Multiple Home Units](https://well-typed.com/blog/2022/01/multiple-home-units/) you can use ghcid to auto-recompile and auto-rerun the `bar` program whenever **any** Haskell source changes, including from libraries (`foo`). To do this, you must pass `--enable-multi-repl` along with the list of libraries to reload, which list should be in the correct order. viz.:
```
ghcid -T Main.main -c 'cabal repl --enable-multi-repl bar foo'
```Now, try modifying `./foo/src/Foo.hs` and ghcid should instantly re-compile and re-run `bar` with the new changes. A demo can be seen [here](https://x.com/sridca/status/1901283945779544362).
## How it works
### The `nixpkgs` tree
The [`nixpkgs`](https://github.com/srid/haskell-multi-nix/tree/nixpkgs) release tag uses raw functions from nixpkgs.
The Haskell infrastructure in nixpkgs provides a package set (an attrset) called `pkgs.haskellPackages`[^ver]. We add two more packages -- `foo` and `bar` (the local packages) -- to this package set. We do this by using the standard nixpkgs overlay API (specifically `extend`, which was created by the implicit `makeExtensible`) defined in [fixed-points.nix](https://github.com/NixOS/nixpkgs/blob/master/lib/fixed-points.nix). After having added the local packages, the result is a *new* package set, which is no different *in essense* to the original package set (we can also put our dependency overrides in the same, or different, overlay). Note that any package in a package set can depend on any other packages; thus, it becomes possible to make `bar` depend on `foo` (see "build-depends" in `./bar/bar.cabal`) even though they come from the same overlay.
[^ver]: The package set `pkgs.haskellPackages` corresponds to the default GHC version. Non-default GHC versions have their own package sets, for e.g.: `pkgs.haskell.packages.ghc924` is the package set for GHC 9.2.4.
### The `master` tree
The `master` branch uses [haskell-flake](https://github.com/srid/haskell-flake) which abstracts much of what we explained above, such that your flake.nix is as small as possible.