Algae.Reader (Algae v1.3.1) View Source

Algae.Reader allows you to pass some readable context around through actions.

This is useful in a number of situations, but the most common case is to weave access to environment variables monadically.

For an illustrated guide to Readers, see Thee Useful Monads.

Examples

iex> use Witchcraft
...>
iex> correct =
...>   monad %Algae.Reader{} do
...>     count    <- ask &Map.get(&1, :count)
...>     bindings <- ask()
...>     return (count == map_size(bindings))
...>   end
...>
iex> sample_bindings = %{count: 3, a: 1, b: 2}
iex> correct_count   = run(correct, sample_bindings)
iex> "Correct count for #{inspect sample_bindings}? #{correct_count}"
"Correct count for %{a: 1, b: 2, count: 3}? true"
...>
iex> bad_bindings = %{count: 100, a: 1, b: 2}
iex> bad_count    = run(correct, bad_bindings)
iex> "Correct count for #{inspect bad_bindings}? #{bad_count}"
"Correct count for %{a: 1, b: 2, count: 100}? false"

Example adapted from source

Link to this section Summary

Functions

Get the wrapped environment. Especially useful in monadic do-notation.

Similar to new/1 and ask/0. Construct an Algae.Reader, but apply a function to the constructed envoronment.

Locally composes a function into a Reader.

Default Elixir.Algae.Reader struct

Reader constructor.

Run the reader function with some argument.

Link to this section Types

Specs

t() :: %Algae.Reader{reader: (... -> any())}

Link to this section Functions

Specs

ask() :: t()

Get the wrapped environment. Especially useful in monadic do-notation.

Examples

iex> run(ask(), 42)
42

iex> use Witchcraft
...>
...> example_fun =
...>   fn x ->
...>     monad %Algae.Reader{} do
...>       e <- ask()
...>       return {x, e}
...>     end
...>   end
...>
...> 42
...> |> example_fun.()
...> |> run(7)
{42, 7}

Specs

ask((any() -> any())) :: t()

Similar to new/1 and ask/0. Construct an Algae.Reader, but apply a function to the constructed envoronment.

The pun here is that you're "asking" a function for something.

Examples

iex> fn x -> x * 10 end
...> |> ask()
...> |> run(5)
50

iex> use Witchcraft
...>
...> foo =
...>   fn words ->
...>     monad %Algae.Reader{} do
...>       loud <- ask &(&1 == String.upcase(&1))
...>       return(words <> (if loud, do: "!", else: "."))
...>     end
...>   end
...>
...> "Hello" |> foo.() |> run("WORLD") # "WORLD" is the context being asked for
"Hello!"

Specs

local(t(), (any() -> any())) :: any()

Locally composes a function into a Reader.

Often the idea is to temporarily adapt the Reader without continuing this change in later runs.

Examples

iex> ask()
...> |> local(fn word -> word <> "!" end)
...> |> local(&String.upcase/1)
...> |> run("o hai thar")
"O HAI THAR!"

Specs

new() :: t()

Default Elixir.Algae.Reader struct

Specs

new((... -> any())) :: t()
new((... -> any())) :: t()

Reader constructor.

Examples

iex> newbie = new(fn x -> x * 10 end)
...> newbie.reader.(10)
100

Specs

run(t(), any()) :: any()

Run the reader function with some argument.

iex> reader = new(fn x -> x + 5 end)
...> run(reader, 42)
47

This is the opposite of new/1.

iex> fun = fn x -> x + 5 end
...> fun.(42) == fun |> new() |> run(42)
true