Witchcraft v1.0.0-beta Witchcraft.Traversable View Source

Walk across a data structure from left to right, running some action on each element in turn.

Similar to applicatives, it can be used to do things like collecting some effect while performing other actions.

Type Class

An instance of Witchcraft.Traversable must also implement Witchcraft.Foldable and Witchcraft.Functor, and define Witchcraft.Foldable.right_fold/3.

[right_fold/3]  Foldable    Functor  [map/2]
                       ↓    ↓
                     Traversable
                   [right_fold/3]

Link to this section Summary

Functions

traverse/2 with arguments reversed

Run each action/effect in sequence (from left to right), and accumulate values along the way

The same as then_traverse, but with the arguments flipped

traverse actions over data, but ignore the results

Convert elements to actions, and then evaluate the actions from left-to-right, and accumulate the results

Link to this section Types

Link to this section Functions

traverse/2 with arguments reversed.

Examples

iex> fn x -> {x, x * 2, x * 10} end |> across([1, 2, 3])
{6, 12, [10, 20, 30]}

iex> fn x -> [x] end |> across({1, 2, 3})
[{1, 2, 3}]

iex> fn x -> [x, x * 5, x * 10] end |> across({1, 2, 3})
[
  {1, 2, 3},
  {1, 2, 15},
  {1, 2, 30}
]

iex> fn x -> [x, x * 5, x * 10] end |> across([1, 2, 3])
[
  #
  [1, 2,  3], [1, 2,  15], [1, 2,  30],
  [1, 10, 3], [1, 10, 15], [1, 10, 30],
  [1, 20, 3], [1, 20, 15], [1, 20, 30],
  #
  [5, 2,  3], [5, 2,  15], [5, 2,  30],
  [5, 10, 3], [5, 10, 15], [5, 10, 30],
  [5, 20, 3], [5, 20, 15], [5, 20, 30],
  #
  [10, 2,  3], [10, 2,  15], [10, 2,  30],
  [10, 10, 3], [10, 10, 15], [10, 10, 30],
  [10, 20, 3], [10, 20, 15], [10, 20, 30]
]

Run each action/effect in sequence (from left to right), and accumulate values along the way.

Examples

iex> sequence([{1, 2, 3}, {4, 5, 6}])
{5, 7, [3, 6]}

iex> [
...>   [1, 2, 3],
...>   [4, 5, 6]
...> ]
...> |> sequence()
[
  [1, 4],
  [1, 5],
  [1, 6],
  [2, 4],
  [2, 5],
  [2, 6],
  [3, 4],
  [3, 5],
  [3, 6]
]
Link to this function then_across(link, traversable) View Source

The same as then_traverse, but with the arguments flipped.

Examples

iex> fn x -> [x, x * 5, x * 10] end
...> |> then_across([1, 2, 3])
[
    #
    %Witchcraft.Unit{}, %Witchcraft.Unit{}, %Witchcraft.Unit{},
    %Witchcraft.Unit{}, %Witchcraft.Unit{}, %Witchcraft.Unit{},
    %Witchcraft.Unit{}, %Witchcraft.Unit{}, %Witchcraft.Unit{},
    #
    %Witchcraft.Unit{}, %Witchcraft.Unit{}, %Witchcraft.Unit{},
    %Witchcraft.Unit{}, %Witchcraft.Unit{}, %Witchcraft.Unit{},
    %Witchcraft.Unit{}, %Witchcraft.Unit{}, %Witchcraft.Unit{},
    #
    %Witchcraft.Unit{}, %Witchcraft.Unit{}, %Witchcraft.Unit{},
    %Witchcraft.Unit{}, %Witchcraft.Unit{}, %Witchcraft.Unit{},
    %Witchcraft.Unit{}, %Witchcraft.Unit{}, %Witchcraft.Unit{}
]
Link to this function then_traverse(traversable, link) View Source
then_traverse(Witchcraft.Traversable.t, Witchcraft.Traversable.link) :: Applicative.t
then_traverse(Witchcraft.Traversable.link, Witchcraft.Traversable.t) :: Applicative.t

traverse actions over data, but ignore the results.

Examples

iex> [1, 2, 3]
...> |> then_traverse(fn x -> [x, x * 5, x * 10] end)
[
    #
    %Witchcraft.Unit{}, %Witchcraft.Unit{}, %Witchcraft.Unit{},
    %Witchcraft.Unit{}, %Witchcraft.Unit{}, %Witchcraft.Unit{},
    %Witchcraft.Unit{}, %Witchcraft.Unit{}, %Witchcraft.Unit{},
    #
    %Witchcraft.Unit{}, %Witchcraft.Unit{}, %Witchcraft.Unit{},
    %Witchcraft.Unit{}, %Witchcraft.Unit{}, %Witchcraft.Unit{},
    %Witchcraft.Unit{}, %Witchcraft.Unit{}, %Witchcraft.Unit{},
    #
    %Witchcraft.Unit{}, %Witchcraft.Unit{}, %Witchcraft.Unit{},
    %Witchcraft.Unit{}, %Witchcraft.Unit{}, %Witchcraft.Unit{},
    %Witchcraft.Unit{}, %Witchcraft.Unit{}, %Witchcraft.Unit{}
]

Convert elements to actions, and then evaluate the actions from left-to-right, and accumulate the results.

For a version without accumulation, see then_traverse/2.

Examples

iex> traverse([1, 2, 3], fn x -> {x, x * 2, x * 10} end)
{6, 12, [10, 20, 30]}

iex> traverse({1, 2, 3}, fn x -> [x] end)
[{1, 2, 3}]

iex> traverse({1, 2, 3}, fn x -> [x, x * 5, x * 10] end)
[
  {1, 2, 3},
  {1, 2, 15},
  {1, 2, 30}
]

iex> traverse([1, 2, 3], fn x -> [x, x * 5, x * 10] end)
[
  #
  [1, 2,  3], [1, 2,  15], [1, 2,  30],
  [1, 10, 3], [1, 10, 15], [1, 10, 30],
  [1, 20, 3], [1, 20, 15], [1, 20, 30],
  #
  [5, 2,  3], [5, 2,  15], [5, 2,  30],
  [5, 10, 3], [5, 10, 15], [5, 10, 30],
  [5, 20, 3], [5, 20, 15], [5, 20, 30],
  #
  [10, 2,  3], [10, 2,  15], [10, 2,  30],
  [10, 10, 3], [10, 10, 15], [10, 10, 30],
  [10, 20, 3], [10, 20, 15], [10, 20, 30]
]

traverse([1, 2, 3], fn x -> %Algae.Maybe.Just{just: x} end)
#=> %Algae.Maybe.Just{just: [1, 2, 3]}

traverse(%Algae.Maybe.Just{just: 4}, fn x -> [x, x * 10] end)
#=> [
#     %Algae.Maybe.Just{just: 4},
#     %Algae.Maybe.Just{just: 40}
#   ]

traverse([1, 2, 3], fn x ->
  if is_even(x) do
    %Algae.Maybe.Just{just: x}
  else
    %Algae.Maybe.Nothing{}
  end
end)
#=> %Algae.Maybe.Nothing{}