Products, Sums and Valid States
What this concept is
A product combines fields: a delivery address has a street AND a postcode. A sum chooses a case: a lookup is Missing OR Found(value). The distinction is about valid combinations, not whether the implementation uses classes. A useful representation makes cases explicit and establishes the remaining invariants at its boundary.
Why it matters here
Existing ownership lessons ask who may change data. This lesson asks what data states should exist at all. Use it before selecting an inheritance hierarchy or adding another boolean flag.
Concrete example
A search result represented by found: bool and value: int | None permits four shapes: false/None, true/value, false/value and true/None. If the contract says found values are integers, the last two are invalid. Use Missing or Found(value) instead. In Python, classes plus a union annotation document this model; runtime construction and decoding still need checks. A dataclass annotation alone does not reject Found("wrong").
In the accompanying lab, inventory state is either an immutable count or an immutable tuple of unit tokens. Its abstract meaning is the number of units available. Count must be a nonnegative integer; every token must be the declared unit marker. A frozen container with mutable nested values would not automatically provide a deep snapshot.
Common confusion / misconception
A sum does not mean every domain rule becomes a static type guarantee. Python is dynamically checked; a union annotation is not runtime enforcement or exhaustive matching. Also distinguish a data value from an entity: equal available counts do not imply two warehouses are the same warehouse.
How to use it
List each case, the fields meaningful in that case and the constraints that still need validation. Draw invalid combinations in the old model. Explain which disappear structurally and which remain protected only by code. Keep boundary validation explicit.
Check yourself
Can a result contain an error reason and a success value simultaneously? Under a success-or-rejection contract, no. Is a valid result necessarily evidence that the operation happened once? No; representation does not prove execution history.
Mini drill or application
Model a document as Draft(text) or Published(text, revision). Define whether empty text is permitted in each case. Compare this with published, text and nullable revision fields. Give two invalid old states and explain what validates revision positivity.
Read this only if stuck
Use selective reading from Cornell’s data types, MIT representation invariants, and Python dataclasses for their respective claims. Revisit the existing SICP reference for evaluation and environments; no full-book assignment is added. Continue with the construction clinic.