A sequence monad is a monadic structure whose context represents zero or more ordered values. In C#, IEnumerable<T> supplies that context: Unit creates a one-element sequence, while Bind applies a sequence-producing function and concatenates the resulting sequences. section 11.4 section 11.3
The familiar sequence operations correspond directly to monadic operations:
- Select is Map: transform every element while preserving the sequence context. section 11.5
- SelectMany is Bind: map each element to a sequence, then flatten by concatenation. section 11.3 section 11.5
- The empty sequence is MZero, the additive identity; binding anything to it produces the empty sequence. section 11.4
- Where can be expressed using only Bind, Unit, and MZero: retain an element with Unit when the predicate succeeds, otherwise return MZero. section 11.4
Filtering through Unit and MZero
A direct filter checks each element and yields matching values. The monadic version instead binds each element to either a one-element sequence or the empty sequence: `Where(items, predicate) = Bind(items, t => predicate(t) ? Unit(t) : MZero)`. Concatenation removes the failed cases while preserving the successful ones. This formulation is correct but allocates many tiny sequences, so the ordinary implementation is usually more efficient. section 11.4
The same operations suggest two complementary analogies. Concatenation behaves like addition, with the empty sequence as zero. SelectMany can form a Cartesian product, making Bind resemble multiplication; multiplying by the empty sequence yields the empty sequence. section 11.4
