Computational monad 2026-10-31
A type constructor with operations and satisfying the monad laws. The first embeds a value; the second sequences a computation with a value-dependent continuation. This is the programming interface to a monad.
Monadic interpreter 2026-10-31
An interpreter whose evaluator returns computations in a computational monad. Its semantic equations specify effect order by sequencing, while monad laws support proofs of program equivalence independently of the particular effects.
Use the three monad laws of the base computational monad. For left identity, at an arbitrary program state ,The last step is the base left identity law. For right identity,The penultimate equality identifies the pair-destructuring function with ; the last uses the base right identity law.
For associativity, expand the two successive uses of sequencing and apply base associativity:No program state is duplicated or reset during these rearrangements: both sides pass to , its output to , and the output of to . By function extensionality,
There is one undifferentiated exception, so use the two alternatives of the Haskell algebraic data type
Maybe: Just x succeeds and Nothing fails. A suitable exception monad transformer is:type ExT m a = m (Maybe a)
result :: Monad m => a -> ExT m a
result x = resultM (Just x)
bind :: Monad m => ExT m a -> (a -> ExT m b) -> ExT m b
bind p f = bindM p (\r -> case r of
Nothing -> resultM Nothing
Just x -> f x)
orelse :: Monad m => ExT m a -> ExT m a -> ExT m a
orelse p q = bindM p (\r -> case r of
Nothing -> q
Just x -> resultM (Just x))
failure :: Monad m => ExT m a
failure = resultM NothingThe distinction between
bindM and bind matters. The handler must inspect the failed alternative using the base computational monad; the transformed bind would propagate failure without running that inspection. The alternative computation q runs only after p returns Nothing; any effects already performed by the base computational monad remain subject to that base's semantics.Left identity follows by selecting
Just x. Right identity follows because either alternative is passed back to resultM. For associativity, base associativity exposes the first alternative: Nothing propagates through both remaining steps; Just x runs f x, with its Nothing and Just alternatives treated identically on both sides. Thus this representation also satisfies the monad laws.type IdM a = a
result :: a -> IdM a
result x = x
bind :: IdM a -> (a -> IdM b) -> IdM b
bind x f = f xAll three monad laws reduce to substitution in function application. There is no additional program state, failure alternative or continuation layer:
The continuation receives both the computed value and the current computer memory. Therefore return invokes it with unchanged computer memory, while sequencing installs a continuation that passes the produced value and updated computer memory to the next computation:
result :: a -> M a
result x k s = k x s
bind :: M a -> (a -> M b) -> M b
bind p f k s = p (\x s' -> f x k s') sFor left identity, expand the two definitions:For right identity,For associativity, both groupings reduce to the same expression:By function extensionality, these establish all three monad laws:
The equivalence holds for every lawful computational monad with the semantic equations above. In particular, effects in are neither discarded nor evaluated twice. Fix an initial semantic environment , and writeExpanding
Let and Val givesThe two steps use associativity and left identity from the monad laws.For the application, evaluating the lambda abstraction yields
result c, where the programming closure satisfies . The singleton argument evaluator reduces toUse left identity to remove the initial result c, then associativity and left identity again:Consequently,The argument relies on the lambda abstraction itself being effect-free, as specified in part (a), and on using the same semantic environment for on each side. No commutativity of effects is assumed. In particular, the proof applies to state monads, exceptions and continuation monads, not merely to the identity monad.Add the abstract syntax tree alternative
Fix Ident Expr. Its syntactic sugar expansion and the semantic equations from part (a) givewhere and . The final step uses left identity from the monad laws and the lookup rule for the newly bound identifier.eval (Fix x e@(Lambda xs body)) rho = result v
where
rho' = extend rho [(x,v)]
v = close e rho'Equivalently, spelling out programming closure construction,The result is a recursive closure, not the result of calling its body. Its self-binding is visible inside that body but does not extend the caller's surrounding semantic environment.