Skip to content

Instantly share code, notes, and snippets.

@SLsthompson
Last active June 9, 2016 19:00
Show Gist options
  • Save SLsthompson/378f3d991ff44a839833 to your computer and use it in GitHub Desktop.
Save SLsthompson/378f3d991ff44a839833 to your computer and use it in GitHub Desktop.
State monad implemented in Elixir
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