Table of contents
Returns
Formal definition
Return is a relation :
holding when , upon completion, places an instance in the caller’s return channel — the value is immediately accessible to the expression or statement that invoked .
One invariant. iff:
- Caller-availability: The instance is in the caller’s scope immediately upon ’s completion — is bound to the result position of the call expression. No additional dispatch, subscription, or polling is needed to access . The caller may use directly in the next computation step. This is the distinguishing condition: the return value is synchronously available to the invoker. Emission (to a side channel) and side-effects (to global state) do not satisfy this condition.
Church: function codomains
Alonzo Church (The Calculi of Lambda-Conversion, 1941): a function returns a value of type — is the codomain, the type of values that come back to the caller. Every application (for ) yields a result in the caller’s scope. Return is the formal content of the codomain: the type to the right of the arrow specifies what comes back.
Beta-reduction makes return concrete: the result of applying to is the term , which is the value returned to the context that contained the application. The redex disappears; the result occupies its position.
In linear lambda calculus (): consumes and returns . The distinction between (consume-and-return) and (consume-and-discard) is whether the operation has a caller-facing return. A function of type consumes and returns the unit — effectively returning nothing meaningful. This is the formal type of a purely side-effecting operation.
Plotkin: evaluation strategies and return values
Gordon Plotkin (Call-by-Name, Call-by-Value and the Lambda-Calculus, 1975): the call-by-value and call-by-name strategies differ in what value is returned to the caller in each case. Call-by-value: arguments are evaluated before the call; the function body is executed once with the value in hand, and the result is returned. Call-by-name: the unevaluated expression is passed; a result is not forced until the caller demands it (lazy return).
The operational correspondence: Plotkin’s standard reduction theorem shows that both strategies reach the same normal form (the return value) when one exists. The return value is independent of strategy — what changes is when the return is forced, not what is returned.
Fischer, Reynolds: continuation-passing style
Michael Fischer (Lambda Calculus Schemata, 1972) and John Reynolds (Definitional Interpreters for Higher-Order Programming Languages, 1972) introduced continuation-passing style (CPS). In CPS, every operation takes an explicit continuation as an extra argument. Returning is replaced by calling — passing the return value to the continuation.
CPS makes the return channel explicit: instead of “O returns to whoever called it,” CPS says “O calls with , where was supplied by whoever called .” The continuation is the first-class reification of the return channel.
CPS transformation of direct-style return: becomes . The equivalence: every direct-style return is a CPS call to the identity continuation .
Moggi: the monad unit as return
Eugenio Moggi (Notions of Computation and Monads, 1991): a monad on a category has a unit (return) . The unit wraps a pure value into a computation — it is the minimal computation that returns with no effects.
In Haskell, return is exactly : return :: a -> m a. Every monadic computation ultimately produces its value by applying return (or pure). The return type encodes the effect type — return gives back a value of type wrapped in the effect context .
Kleisli composition: — monadic return is the unit for Kleisli composition: return >=> f = f and f >=> return = f. This makes return the identity element for the algebra of effectful computations.
Open questions
- Whether return and emit are formally dual in the category of operations — whether there is a coend or profunctor construction that makes (giving to the caller) dual to (giving to an environment channel), and whether this duality corresponds to the caller/environment decomposition of a program’s context.
- Whether the CPS representation of return (calling a continuation) and the direct-style return are inter-translatable without loss in all settings — specifically, whether any operation that returns has a faithful CPS translation in which captures all uses of the return value, including uses in type-dependent contexts.