nix-playgraound/notes/027-haskell-deriving.md

1.7 KiB

Haskell Deriving Strategies

This note covers 24-haskell-deriving/, which uses deriving stock and GeneralizedNewtypeDeriving to build useful behavior for release-planning types with very little manual code.


1. What the Example Derives

The example derives three kinds of behavior:

  • ordering and display for enums and records,
  • enumeration for the environment list, and
  • numeric and semigroup behavior for newtypes.

Those derived instances are then used directly in the program:

  • allEnvironments comes from Enum and Bounded,
  • sortedTargets relies on derived Ord, and
  • totalFailureBudget relies on derived Num.

2. Why the Constructor Order Matters

Derived ordering is not magical. It follows constructor order for sum types, and field order for product types.

That matters in this example:

  • Priority lists Urgent before Standard and Background, so urgent work sorts first, and
  • ReleaseTarget stores environment and priority before the service name, so the derived record ordering matches the intended rollout order.

This is the main teaching point: derived instances are only as good as the domain shape you give them.


3. Why the Newtypes Are Useful

BatchName and FailureBudget are wrappers, but they still need behavior.

GeneralizedNewtypeDeriving lets the example reuse the underlying instances:

  • BatchName derives Semigroup and Monoid, and
  • FailureBudget derives Num and Ord.

That means the code can concatenate names and sum budgets without unpacking the wrappers everywhere.


4. Commands to Try

cd 24-haskell-deriving

nix develop
cabal run
cabal test

nix build
./result/bin/mini-deriving

nix run
nix flake check