Created
April 2, 2012 23:51
-
-
Save kputnam/2288109 to your computer and use it in GitHub Desktop.
State monad in CoffeeScript
This file contains bidirectional Unicode text that may be interpreted or compiled differently than what appears below. To review, open the file in an editor that reveals hidden Unicode characters.
Learn more about bidirectional Unicode characters
# Actions | |
################################################################### | |
put = (n) -> (state, count) -> | |
{state: n, value: null, count: count + 1} | |
get = (state, count) -> | |
{state: state, value: state, count: count} | |
update = (f) -> (state, count) -> | |
{state: f(state), value: null, count: count + 1} | |
# Combinators | |
################################################################### | |
unit = (value) -> (state, count) -> | |
{state: state, value: value, count: count} | |
bind = (x, f) -> (state, count) -> | |
tuple = x(state, count) | |
f(tuple.value)(tuple.state, tuple.count) | |
# Evaluators | |
################################################################### | |
# Return the entire monadic value (state, value, count) | |
run = (computation, initialState) -> | |
computation(initialState, 0) | |
# Return the resulting value | |
eval = (computation, initialState) -> | |
computation(initialState, 0).value | |
# Return the resulting state | |
exec = (computation, initialState) -> | |
computation(initialState, 0).state | |
# Return how many times state was written | |
count = (computation, initialState) -> | |
computation(initialState, 0).count | |
# Example | |
################################################################### | |
also = (a) -> (b) -> a && b | |
test = | |
bind get, (x) -> | |
bind put(x % 2 == 0), -> | |
bind update(also(x % 3 == 0)), -> | |
bind update(also(x % 5 == 0)), -> | |
bind get, (t) -> | |
unit(if x > 100 && t \ | |
then "Big multiple of 2, 3, 5: #{x}" | |
else "Dunno: #{x}") | |
# This shows three writes to the state | |
# run(test, 300) | |
# run(test, 301) | |
if exports? | |
exports.put = put | |
exports.get = get | |
exports.update = update | |
exports.unit = unit | |
exports.bind = bind | |
exports.run = run | |
exports.eval = eval | |
exports.exec = exec | |
exports.count = count | |
exports.test = test |
Sign up for free
to join this conversation on GitHub.
Already have an account?
Sign in to comment