A type-lifting function, conventionally named unit, takes an ordinary value and places it in a computation type. For state-threading computations, it constructs an action that returns the supplied value while passing its input state through unchanged: unit(a) is s => (a, s). The value becomes available to later composition without inventing a state transition. section 6.8
def unit[S, A](a: A): State[S, A] = s => (a, s)
The implementation makes the two obligations explicit: return a, and return the original s unchanged. section 6.8
This small operation supplies neutral starting values for larger computations. A state sequence begins with an action containing an empty list, then combines each action with that accumulator. Since the initial action does not consume or alter state, sequencing can build a result list while preserving the normal state flow of the real actions. section 6.8 section 11.7
Lifting a value into State
For State[Int, A], unit(List[(Int, A)]()) creates an action that initially yields an empty list and leaves the integer state intact. A fold can then use get and set to number elements, extending that lifted empty result one element at a time. section 11.5.2
The same name captures a broader pattern, but each computation type gives lifting its own meaning. Par.unit promotes a value to a parallel computation; Option uses Some; List creates a one-element list; Gen supplies a generated value. Unit therefore changes the surrounding computational context while retaining the supplied result. section 7.1.1 section 11.7
Unit supports derived combinators because it can introduce an ordinary value wherever a computation is required:
- map can transform a computed result by flatMapping and lifting f(a) back into the same type. section 11.2.1
- map2 and traverse use unit as the empty or neutral computation from which combined results are built. section 12.1 section 12.2
- flatMap identity laws say that lifting before a continuation adds no observable extra computation, and lifting after one preserves it. section 11.4.3
In a Monad, unit and flatMap are chosen as a minimal primitive set. From them come map and map2, avoiding repeated implementations across Parser, Gen, Par, Option, and State. The Monad contract does not prescribe the hidden behavior of a computation; it requires associativity and identity laws, including the laws governing unit. section 11.2.1 section 11.7
Unit in parallel mapping
A Par value can be mapped without running it by pairing it with unit(()) and ignoring that placeholder in map2. This expresses sorting as a transformation inside Par rather than extracting a result, sorting it, and repackaging it. section 7.2.1 section 7.2.1
Applicative functors retain unit but pair it with map2 rather than flatMap. That supports context-free combination, traversal, and lifting functions into an effect, but cannot flatten F[F[A]] or make later computations depend on earlier results. Monad adds those context-sensitive capabilities through flatMap or join. section 12.2 section 12.3 section 12.9



