50 lines
1.6 KiB
Text
50 lines
1.6 KiB
Text
-- 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)).
|