add a few monad examples

This commit is contained in:
darkf 2013-10-25 02:31:35 -07:00
parent ef80d723ca
commit ebcab6b75f
3 changed files with 89 additions and 0 deletions

View File

@ -0,0 +1,20 @@
-- The Identity monad is very simple - it wraps a value, and then when bind is called it applies that value
-- to the function, and then the result is the new Identity. To get at the value, use runIdentity.
-- Since we're dynamically typed and we don't have subtyping, we use a pair to identify Identities.
--
-- This probably doesn't serve a purpose right now, except to show off monads.
return(x) -> ("identity", x). -- wrap a value
bind(("identity", x), f) -> f(x). -- apply a value
runIdentity(("identity", x)) -> x. -- unwrap a value
-- equivalent to 10 * 4 + 2, but in monadic form (yay!)
forty_two = bind(return(10), \x ->
bind(return(x*4), \y ->
return(y + 2)
)
).
-- print the representation and the actual value
print(forty_two).
print(runIdentity(forty_two)).

View File

@ -0,0 +1,19 @@
-- a Maybe monad. Wraps a value like ("just", 5) or ("nothing").
-- Bind returns ("nothing") on ("nothing"), or unwraps the value and calls the function on bind.
return(x) -> ("just", x). -- wrap a value
bind(("just", x), f) -> f(x). -- apply a value
bind(("nothing"), f) -> ("nothing").
-- equivalent to 10 * 4 + 2, but in monadic form (yay!)
forty_two = bind(return(10), \x ->
bind(return(x*4), \y ->
return(y + 2)
)
).
-- this will just return ("nothing")
nothing = bind(("nothing"), \x -> x+10).
print(forty_two).
print(nothing).

View File

@ -0,0 +1,50 @@
-- 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)).