An algebraic law states an equation or behavioral property that an API’s operations must satisfy. Treating an API as operations plus laws makes type-directed reasoning more like symbolic algebra: implementations may vary, but they must preserve the stated relationships. Writing laws explicitly exposes design choices that informal expectations can hide. section 7.3
A law often begins as a concrete identity and is then generalized. For parallel computations, mapping over a completed value should agree with completing the mapped value: unit(x).map(f) == unit(f(x)). Equivalence is observed by running both computations on any valid ExecutorService and comparing their Future results. This prevents unit or map from inspecting values and changing behavior for particular cases. section 7.3.1
unit(x).map(f) == unit(f(x)) #1 unit(x).map(id) == unit(id(x)) #2 unit(x).map(id) == unit(x) #3 y.map(id) == y #4
Follow a specific mapping example through substitution of the identity function to obtain the simpler identity law y.map(id) == y. section 7.3.1
Laws guide API design and reasoning in several ways:
- Constrain meaning and implementation choices, rather than merely document preferred results. section 7.3.1
- Supply high-level properties suitable for automated property-based tests, separating behavior specifications from generated test cases. section 8.0
- Reveal shared structure when analogous operations satisfy the same law across Par, Gen, List, LazyList, Option, and State. section 8.4
- Support algebraic design: specify operations and their relationships before committing to a data representation. section 9.1
Associativity preserves sequencing
Two nested flatMap expressions can look different after expanding a for-comprehension, yet should behave alike. The monad associative law requires x.flatMap(f).flatMap(g) == x.flatMap(a => f(a).flatMap(g)). For Option, the law can be checked by expanding both sides for its only cases: None and Some(v). Recasting monadic functions as Kleisli arrows makes the same requirement a familiar associative composition equation. section 11.4.1 section 11.4.2
Laws can define an abstraction independently of representation. A functor is characterized by structure-preserving map, with identity and composition laws. A monad supplies a minimal set of combinators—such as unit and flatMap—and satisfies associativity and identity. The contract does not prescribe internal behavior; satisfying the laws grants access to derived combinators. section 11.5 section 11.7
The payoff is reusable, testable APIs. A minimal set of primitive operations plus law-respecting derived combinators reduces duplication, while algebraic structure can justify splitting computations into independently computed chunks and composing larger calculations from smaller ones. section 7.6 section 10.0

