lamb/examples/monads/state_monad.lamb

51 lines
1.6 KiB
Plaintext

-- The State monad. State wraps a stateful computation that results in a pair of a return value and a state, with functions for manipulating them.
-- It's useful for passing around functions that modify state.
-- ("state", f) is a wrapper around a stateful computation. You shouldn't apply this directly,
-- but use runState().
-- state computation that sets the result but leaves the state unchanged
return(x) -> ("state", \st -> (x, st)).
-- take a state computation and apply it with a state, returning a (result, state) tuple
runState(("state", f), x) -> f(x).
-- we want to apply LHS and RHS sequentially, RHS taking in a result and returning a new state.
bind(("state", h), f) ->
("state", \st -> do -- take in a state
-- this is the same as runState(h, st) where h is the first argument to bind
-- but we want to use the pattern match on "state" so that we don't end up with some
-- other value, so we just do it manually here.
(result, newstate) = h(st); -- apply our LHS computation to it, getting our new state tuple
rightstate = f(result); -- pass the result part into the new function, getting a new state computation
runState(rightstate, newstate)
end).
-- sets the result to the state
get = ("state", \st -> (st, st)).
-- sets the state, and the result to ()
put(st) -> ("state", \_ -> ((,), st)).
derp = return(10).
herp = bind(derp, \x ->
bind(return(x+2), \y ->
return(y+2)
)
).
ferp = bind(derp, \x ->
bind(get, \y ->
bind(put(x+y), \_ ->
return(x*y)
)
)
).
print(runState(derp, 20)).
print(runState(herp, 20)).
print(runState(ferp, 20)).