Add a mini-haskell project with Cabal and flakes
This commit is contained in:
parent
2c2af9ecda
commit
73fbd6c176
16
05-haskell/app/Main.hs
Normal file
16
05-haskell/app/Main.hs
Normal file
@ -0,0 +1,16 @@
|
||||
module Main where
|
||||
|
||||
import System.Environment (getArgs)
|
||||
|
||||
greeting :: String -> String
|
||||
greeting name = "hello, " ++ name ++ ", from Haskell and Nix"
|
||||
|
||||
main :: IO ()
|
||||
main = do
|
||||
args <- getArgs
|
||||
let name =
|
||||
case args of
|
||||
[] -> "learner"
|
||||
firstArg : _ -> firstArg
|
||||
|
||||
putStrLn (greeting name)
|
||||
27
05-haskell/flake.lock
generated
Normal file
27
05-haskell/flake.lock
generated
Normal file
@ -0,0 +1,27 @@
|
||||
{
|
||||
"nodes": {
|
||||
"nixpkgs": {
|
||||
"locked": {
|
||||
"lastModified": 1776548001,
|
||||
"narHash": "sha256-ZSK0NL4a1BwVbbTBoSnWgbJy9HeZFXLYQizjb2DPF24=",
|
||||
"owner": "NixOS",
|
||||
"repo": "nixpkgs",
|
||||
"rev": "b12141ef619e0a9c1c84dc8c684040326f27cdcc",
|
||||
"type": "github"
|
||||
},
|
||||
"original": {
|
||||
"owner": "NixOS",
|
||||
"ref": "nixos-unstable",
|
||||
"repo": "nixpkgs",
|
||||
"type": "github"
|
||||
}
|
||||
},
|
||||
"root": {
|
||||
"inputs": {
|
||||
"nixpkgs": "nixpkgs"
|
||||
}
|
||||
}
|
||||
},
|
||||
"root": "root",
|
||||
"version": 7
|
||||
}
|
||||
46
05-haskell/flake.nix
Normal file
46
05-haskell/flake.nix
Normal file
@ -0,0 +1,46 @@
|
||||
{
|
||||
# Builds a tiny Haskell executable from a local Cabal package, and
|
||||
# provides a matching dev shell for editing and running it.
|
||||
description = "A minimal Haskell project with Cabal and flakes";
|
||||
|
||||
inputs = {
|
||||
nixpkgs.url = "github:NixOS/nixpkgs/nixos-unstable";
|
||||
};
|
||||
|
||||
outputs =
|
||||
{ self, nixpkgs, ... }:
|
||||
let
|
||||
system = "x86_64-linux";
|
||||
pkgs = import nixpkgs { inherit system; };
|
||||
inherit (pkgs) haskellPackages;
|
||||
project = haskellPackages.callCabal2nix "mini-haskell" ./. { };
|
||||
in
|
||||
{
|
||||
packages.${system}.default = project;
|
||||
|
||||
apps.${system}.default = {
|
||||
type = "app";
|
||||
program = "${self.packages.${system}.default}/bin/mini-haskell";
|
||||
meta.description = "Run the minimal Haskell example.";
|
||||
};
|
||||
|
||||
devShells.${system}.default = pkgs.mkShell {
|
||||
packages = [
|
||||
haskellPackages.ghc
|
||||
pkgs.cabal-install
|
||||
pkgs.haskell-language-server
|
||||
];
|
||||
};
|
||||
|
||||
checks.${system}.greeting = pkgs.runCommand "mini-haskell-greeting" { } ''
|
||||
output="$(${self.packages.${system}.default}/bin/mini-haskell flakes)"
|
||||
|
||||
if [ "$output" = "hello, flakes, from Haskell and Nix" ]; then
|
||||
echo ok > "$out"
|
||||
else
|
||||
echo "unexpected output: $output" >&2
|
||||
exit 1
|
||||
fi
|
||||
'';
|
||||
};
|
||||
}
|
||||
10
05-haskell/mini-haskell.cabal
Normal file
10
05-haskell/mini-haskell.cabal
Normal file
@ -0,0 +1,10 @@
|
||||
cabal-version: 2.4
|
||||
name: mini-haskell
|
||||
version: 0.1.0.0
|
||||
build-type: Simple
|
||||
|
||||
executable mini-haskell
|
||||
main-is: Main.hs
|
||||
hs-source-dirs: app
|
||||
build-depends: base >=4.14 && <5
|
||||
default-language: Haskell2010
|
||||
73
notes/007-haskell.md
Normal file
73
notes/007-haskell.md
Normal file
@ -0,0 +1,73 @@
|
||||
# Haskell Project
|
||||
|
||||
This note covers `05-haskell/`, which packages a tiny Cabal executable with Nix 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 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 both how to build a Haskell program and how to work on it interactively.
|
||||
|
||||
---
|
||||
|
||||
## 2. The Package Build
|
||||
|
||||
`pkgs.haskellPackages.callCabal2nix` reads the local Cabal file and produces a Nix derivation for the executable:
|
||||
|
||||
```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.
|
||||
|
||||
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 Check
|
||||
|
||||
`checks.<system>.greeting` runs the built executable with an argument and compares its output to an expected string.
|
||||
|
||||
That gives `nix flake check` one concrete behavior to verify:
|
||||
|
||||
- the Cabal package evaluates,
|
||||
- the executable builds, and
|
||||
- the program runs and prints the expected result.
|
||||
|
||||
---
|
||||
|
||||
## 5. Commands to Try
|
||||
|
||||
```bash
|
||||
cd 05-haskell
|
||||
|
||||
nix develop
|
||||
cabal run
|
||||
cabal run -- flakes
|
||||
|
||||
nix build
|
||||
./result/bin/mini-haskell
|
||||
./result/bin/mini-haskell flakes
|
||||
|
||||
nix run
|
||||
nix run . -- flakes
|
||||
nix flake check
|
||||
```
|
||||
Loading…
x
Reference in New Issue
Block a user