diff --git a/examples/monads/identity_monad.lamb b/examples/monads/identity_monad.lamb new file mode 100644 index 0000000..7f091b6 --- /dev/null +++ b/examples/monads/identity_monad.lamb @@ -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)). \ No newline at end of file diff --git a/examples/monads/maybe_monad.lamb b/examples/monads/maybe_monad.lamb new file mode 100644 index 0000000..cd7b217 --- /dev/null +++ b/examples/monads/maybe_monad.lamb @@ -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). diff --git a/examples/monads/state_monad.lamb b/examples/monads/state_monad.lamb new file mode 100644 index 0000000..e4a666c --- /dev/null +++ b/examples/monads/state_monad.lamb @@ -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)).