Last active
June 9, 2016 19:00
-
-
Save SLsthompson/378f3d991ff44a839833 to your computer and use it in GitHub Desktop.
State monad implemented in Elixir
This file contains hidden or 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
defmodule State do | |
# At each stage of computation, State builds a function. That | |
# function accepts an "initial state" as an argument and returns | |
# a tuple containing a final computed value, and a final state | |
# The basis of State accepts a value and returns a function. | |
# The function returned accepts a state and returns a tuple with the | |
# value and the state. | |
def unit(value) do | |
# this could be &({value, &1}), but this way is a bit more explicit | |
# about what's going on. | |
fn (state) -> {value, state} end | |
end | |
# Bind accepts a monadic value (which in State is a function that returns a tuple) | |
# The function which binds the value back into state takes a value as a | |
# parameter and returns a State entity (which is itself a function) | |
# | |
# Like the rest of State, the function returned must take an initial | |
# state and return a tuple of a value and a final state. | |
def bind(monadic, bind_to) do | |
# 1. return a function that takes a state (and returns a {value, state} tuple) | |
fn (state) -> | |
# 2. We extract the "current" value and next_state by calling the | |
# State function that was passed to us. | |
{value, intermediate_state} = monadic.(state) | |
# 3. Pass the current value to the binding function. The binding | |
# function will return a State... a function. That function accepets a state | |
# and returns a tuple with a finals state and a final value. We call | |
# THAT function with the intermediate state to get a final value and final state | |
# | |
# (at least locally final relative to this stage of the bind) | |
bind_to.(value).(intermediate_state) | |
end | |
end | |
def extract_value(monadic, initial_state) do | |
elem(monadic.(initial_state), 1) | |
end | |
def extract_state(monadic, initial_state) do | |
elem(monadic.(initial_state), 2) | |
end | |
end |
Sign up for free
to join this conversation on GitHub.
Already have an account?
Sign in to comment