1.4 KiB
Haskell NonEmpty Waves
This note covers 32-haskell-nonempty-waves/, which models rollout plans with NonEmpty so every plan is guaranteed to have at least one wave.
1. Why NonEmpty Matters
A rollout plan with zero waves is not meaningful.
Using [Wave] would force every caller to handle an impossible-but-representable empty case. This example makes that impossible state unrepresentable
instead:
planWaves :: NonEmpty Wave
That means the rendering code can safely ask for the first and last wave without defensive checks.
2. What the Example Builds
The example turns a release job into:
- one wave for a rolling rollout, or
- two waves for a canary rollout.
Both cases still share the same output type. That is the real teaching point: NonEmpty lets you preserve list-like behavior while tightening the
domain guarantee.
3. Why This Is Better Than a Runtime Check
You could build a plain list and reject [] later.
That would move the invariant into comments and runtime branches. NonEmpty pushes the guarantee into the type itself, which is more precise and
easier to trust.
4. Commands to Try
cd 32-haskell-nonempty-waves
nix develop
cabal run
cabal run -- api:production:canary:20:6
cabal test
nix build
./result/bin/mini-waves api:production:canary:20:6
nix run . -- api:production:canary:20:6
nix flake check