Algae v1.2.3 Algae.State View Source

Algae.State describes a wrapped function that can be used to pass around some "hidden" pure state.

This has numerous applications, but the primary advantage is purity. The state gets passed around with the value, and the monadic DSL helps it feel more natural than passing everything around by hand.

In many ways, Algae.State is a generalization of Algae.Reader and Algae.Writer. See Thee Useful Monads a nice, illustrated guide to how these work and relate.

Anatomy

          # To pass in concrete values
                          
%Algae.State{runner: fn access -> {value, state} end}
                                           
           # "explicit" value position     "hidden" state position

Examples

iex> use Witchcraft
...>
...> %Algae.State{}
...> |> monad do
...>   name <- get()
...>   let result = "Hello, #{name}!"
...>
...>   put result
...>   modify &String.upcase/1
...>
...>   return result
...> end
...> |> run("world")
{
  "Hello, world!",
  "HELLO, WORLD!"
}

iex> use Witchcraft
...>
...> pop  = fn -> state(fn([x | xs])       -> {x, xs}   end) end
...> pull = fn -> state(fn(list = [x | _]) -> {x, list} end) end
...> push = &state(fn(xs) -> {%Witchcraft.Unit{}, [&1 | xs]} end)
...>
...> %Algae.State{}
...> |> monad do
...>   push.(["a"])
...>   push.(["b"])
...>   push.(["c"])
...>   push.(["d"])
...>   push.(["e"])
...>
...>   z <- pop.()
...>   y <- pop.()
...>   x <- pop.()
...>
...>   push.(x <> y <> z)
...>   pull.()
...> end
...> |> evaluate([])
["c", "d", "e"]

Link to this section Summary

Functions

Run the enclosed Algae.State runner, and return the value (no state)

Run the enclosed Algae.State runner, and return the state (no value)

Set both sides of an Algae.State struct

Set both sides of an Algae.State struct, plus running a function over the value portion of the inner state

Run a function over the "state" portion of the runner

Construct a new Algae.State struct from a state runner in the form fn x -> {y, z} end

Set the stateful position of an Algae.Struct

Extract the runner from an Algae.State

Run an Algae.State by passing in some initial state to actualy run the enclosed state runner

Alias for new/1 that reads better when importing the module

Link to this section Types

Link to this type

runner() View Source
runner() :: (any() -> {any(), any()})

Link to this type

t() View Source
t() :: %Algae.State{runner: runner()}

Link to this section Functions

Link to this function

evaluate(state, value) View Source
evaluate(Algae.State.t(), any()) :: any()

Run the enclosed Algae.State runner, and return the value (no state).

Examples

iex> use Witchcraft
...>
...> %Algae.State{}
...> |> monad do
...>   name <- get()
...>   put "Ignored"
...>   return "Hello, #{name}!"
...> end
...> |> evaluate("world")
"Hello, world!"
Link to this function

execute(state, value) View Source
execute(Algae.State.t(), any()) :: any()

Run the enclosed Algae.State runner, and return the state (no value).

Examples

iex> fn x -> x + 1 end
...> |> get()
...> |> execute(1)
1

iex> use Witchcraft
...>
...> %Algae.State{}
...> |> monad do
...>   whatevs <- get()
...>   put "State"
...>   return "Hello, #{whatevs}!"
...> end
...> |> execute("world")
"State"

Set both sides of an Algae.State struct.

Examples

iex> run(get(), 1)
{1, 1}

Set both sides of an Algae.State struct, plus running a function over the value portion of the inner state.

Examples

iex> fn x -> x * 10 end
...> |> get()
...> |> run(4)
{40, 4}

Run a function over the "state" portion of the runner.

Examples

iex> fn x -> x + 1 end
...> |> modify()
...> |> run(42)
{%Witchcraft.Unit{}, 43}

iex> use Witchcraft
...>
...> %Algae.State{}
...> |> monad do
...>   name <- get()
...>
...>   put "State"
...>   modify &String.upcase/1
...>
...>   return "Hello, #{name}!"
...> end
...> |> run("world")
{"Hello, world!", "STATE"}

Construct a new Algae.State struct from a state runner in the form fn x -> {y, z} end

Examples

iex> new(fn x -> {x + 1, x} end).runner.(42)
{43, 42}

Set the stateful position of an Algae.Struct.

Not unlike Algae.Writer.tell/1.

Examples

iex> 1
...> |> put()
...> |> run(0)
{%Witchcraft.Unit{}, 1}

Extract the runner from an Algae.State.

Can be used as a curried version of run/2.

Examples

iex> inner = fn x -> {0, x} end
...>
...> run(%Algae.State{runner: inner}).(42) == inner.(42)
true

Run an Algae.State by passing in some initial state to actualy run the enclosed state runner.

Examples

iex> use Witchcraft
...>
...> %Algae.State{}
...> |> of(2)
...> |> run(0)
{2, 0}

Alias for new/1 that reads better when importing the module.

Examples

iex> state(fn x -> {x + 1, x} end).runner.(42)
{43, 42}