add a few monad examples
This commit is contained in:
parent
ef80d723ca
commit
ebcab6b75f
|
@ -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)).
|
|
@ -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).
|
|
@ -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)).
|
Loading…
Reference in New Issue