Rand[A] is a type alias for RNG => (A, RNG). It represents a state action: a program that consumes an RNG, produces an A, and returns the next RNG without mutating state. section 6.4 section 6.8
type Rand[+A] = RNG => (A, RNG)
The alias makes state actions easier to name while preserving their underlying function representation. section 6.4
A direct implementation must repeatedly unpack a value and manually pass the returned RNG into the next computation. Rand separates that bookkeeping from the calculation being expressed. section 6.8
Rand actions can be composed through a small set of combinators:
- unit creates an action that returns a constant and leaves the RNG unchanged. section 6.4
- map transforms an action’s result without changing how the resulting RNG is threaded. section 6.4
- map2 combines two actions, passing the RNG returned by the first into the second. section 6.8
- flatMap uses a generated value to choose the next Rand action, enabling retries and value-dependent computation. section 6.4.2
- sequence turns a list of Rand actions into one action producing a list of results. section 6.8
A testable die roll
A die roll can be built from a bounded random action: `def rollDie: Rand[Int] = map(nonNegativeLessThan(6))(_ + 1)`. The bounded generator uses flatMap to retry values that would make modulo-based selection skewed. Supplying the same RNG state reproduces the same result, making the off-by-one error observable and testable. section 6.4.2 section 6.4.2
The pattern generalizes beyond randomness. State[S, A] uses the same function shape, S => (A, S), and the same combinators to remove manual state threading from other stateful computations. section 6.8
