72 lines
2.0 KiB
Markdown
72 lines
2.0 KiB
Markdown
# Haskell foldMap Summaries
|
|
|
|
This note covers `29-haskell-foldmap-summary/`, which summarizes deployment events with one `foldMap` pass into a monoidal report value.
|
|
|
|
---
|
|
|
|
## 1. Why `foldMap` Fits This Problem
|
|
|
|
Each deployment event contributes a small piece of information:
|
|
|
|
- one deployment count,
|
|
- maybe one production count,
|
|
- some replica count,
|
|
- maybe one failed service,
|
|
- some owners,
|
|
- maybe one cancellation flag, and
|
|
- one candidate for the largest rollout.
|
|
|
|
Those pieces all combine associatively, which makes the problem a good fit for monoids.
|
|
|
|
The example expresses that directly:
|
|
|
|
```haskell
|
|
summarizeEvents :: [DeploymentEvent] -> DeploymentSummary
|
|
summarizeEvents = foldMap summarizeEvent
|
|
```
|
|
|
|
---
|
|
|
|
## 2. What the Summary Type Encodes
|
|
|
|
`DeploymentSummary` is not one big counter. It is a record of smaller monoidal fields:
|
|
|
|
- `Count` for totals,
|
|
- `Set String` for failed services and owners,
|
|
- `CancelledSeen` for a yes-or-no flag, and
|
|
- `LargestReplicas` for the maximum rollout size.
|
|
|
|
That is the main teaching point: when each field has a lawful combine operation, the whole summary can combine cleanly too.
|
|
|
|
---
|
|
|
|
## 3. Why This Is Better Than a Manual Loop
|
|
|
|
The example could have used an explicit left fold and updated every field by hand inside the loop.
|
|
|
|
`foldMap` is cleaner here because it splits the work into two precise ideas:
|
|
|
|
1. how one event becomes a summary fragment, and
|
|
2. how summary fragments combine.
|
|
|
|
That makes the aggregation easier to extend without tangling the parsing and report logic.
|
|
|
|
---
|
|
|
|
## 4. Commands to Try
|
|
|
|
```bash
|
|
cd 29-haskell-foldmap-summary
|
|
|
|
nix develop
|
|
cabal run
|
|
cabal run -- api:production:succeeded:3:platform,security worker:staging:failed-db-lock:1:ops ui:production:cancelled:2:frontend
|
|
cabal test
|
|
|
|
nix build
|
|
./result/bin/mini-summary api:production:succeeded:3:platform,security worker:staging:failed-db-lock:1:ops ui:production:cancelled:2:frontend
|
|
|
|
nix run . -- api:production:succeeded:3:platform,security worker:staging:failed-db-lock:1:ops ui:production:cancelled:2:frontend
|
|
nix flake check
|
|
```
|