nix-playgraound/notes/035-haskell-nonempty-waves.md

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