Witchcraft v1.0.0 Witchcraft.Foldable View Source
Data that can be folded over to change its structure by altering or combining elements.
Unlike Witchcraft.Functors
s, the end result will not respect the original structure
unless you build it back up manually.
Examples
iex> right_fold([1, 2, 3], 0, &+/2) # sum
6
Properties
People are working on Foldable properties. This is one of the exceptions to there needing to conform to properties. In the meantime, we are testing that naturality is preserved, which is be a free theorm.
If that fails, something is very wrong with the instance.
Type Class
An instance of Witchcraft.Foldable
define Witchcraft.Foldable.right_fold/3
.
Foldable [right_fold/3]
Link to this section Summary
Functions
Check if a foldable is full of only true
s
The same as all?/1
, but with a custom predicate matcher
Check if a foldable contains any true
s
The same as all?/1
, but with a custom predicate matcher
Check if a foldable data structure is empty
Lift a function over a foldable structure generating lists of results, and then concatenate the resulting lists
Concatenate all lists in a foldable structure
Combine all elements using monoidal append
Map a functional over all elements and fold
them together
The same as left_fold/3
, but uses the first element as the seed
Left-associative fold over a structure to alter the structure and/or reduce it to a single summary value
Count the number of elements in a foldable structure
Find the maximum element in a foldable structure using the default ordering
from Witchcraft.Ord
Find the maximum element in a foldable structure using a custom comparitor
Check if a foldable structure contains a particular element
Find the minimum element in a foldable structure using the default ordering
from Witchcraft.Ord
Find the maximum element in a foldable structure using a custom comparitor
Test whether the structure is empty. The default implementation is optimized for structures that are similar to lists, because there is no general way to do better
Product of all numbers in a foldable
Get a random element from a foldable structure
The same as right_fold/3
, but uses the first element as the seed
Right-associative fold over a structure to alter the structure and/or reduce it to a single summary value. The right-association makes it possible to cease computation on infinite streams of data
Sum all numbers in a foldable
Run each action from left to right, discarding all values
The same as then_traverse
, but with the arguments flipped
traverse
actions over data, but ignore the results
Turn any Foldable
into a List
Link to this section Types
Link to this section Functions
Check if a foldable is full of only true
s
Examples
iex> all?([true, true, false])
false
iex> all?({true, true, false})
false
%BinaryTree{
left: true,
right: %BinaryTree{
left: true,
right: false
}
} |> all?()
#=> false
all?(Witchcraft.Foldable.t, (any -> boolean)) :: boolean
The same as all?/1
, but with a custom predicate matcher
Examples
iex> import Integer
...> all?([1, 2, 3], &is_odd/1)
false
%BinaryTree{
left: 1,
right: %BinaryTree{
left: 2,
right: 3
}
}
|> all?(&Integer.is_odd?/1)
#=> false
Check if a foldable contains any true
s
Examples
iex> any? [true, true, false]
true
%BinaryTree{
left: true,
right: %BinaryTree{
left: true,
right: false
}
} |> any?()
#=> true
Not that the Tuple
instance behaves somewhat conterintuitively
iex> any? {true, true, false}
false
iex> any? {true, false, true}
true
any?(Witchcraft.Foldable.t, (any -> boolean)) :: boolean
The same as all?/1
, but with a custom predicate matcher
Examples
iex> require Integer
...> any?([1, 2, 3], &Integer.is_odd/1)
true
%BinaryTree{
left: 1,
right: %BinaryTree{
left: 2,
right: 3
}
}
|> any(&Integer.is_odd?/1)
#=> true
Check if a foldable data structure is empty
Examples
iex> empty?("")
true
iex> empty?("hi")
false
iex> empty?(%{})
true
flat_map(Witchcraft.Foldable.t, (any -> [any])) :: [any]
Lift a function over a foldable structure generating lists of results, and then concatenate the resulting lists
Examples
iex> flat_map([1, 2, 3, 4, 5, 6], fn x -> [x, x] end)
[1, 1, 2, 2, 3, 3, 4, 4, 5, 5, 6, 6]
iex> flat_map({1, 2, 3, 4, 5, 6}, fn x -> [x, x] end)
[6, 6]
%BinaryTree{
left: 1,
right: %BinaryTree{
left: 2,
right: 3
}
}
|> flat_map(fn x -> [x, x] end)
#=> [1, 1, 2, 2, 3, 3]
Concatenate all lists in a foldable structure
Examples
iex> flatten([[1, 2, 3], [4, 5, 6], [7, 8, 9]])
[1, 2, 3, 4, 5, 6, 7, 8, 9]
iex> flatten({[1, 2, 3], [4, 5, 6], [7, 8, 9]})
[7, 8, 9]
%BinaryTree{
left: [1, 2, 3],
right: %BinaryTree{
left: [4, 5],
right: [6]
}
}
|> flatten()
#=> [1, 2, 3, 4, 5, 6]
Combine all elements using monoidal append
Examples
iex> fold([1, 2, 3])
6
iex> fold([[1, 2, 3], [4, 5, 6], [7, 8, 9]])
[1, 2, 3, 4, 5, 6, 7, 8, 9]
fold_map(Witchcraft.Foldable.t, (... -> any)) :: any
Map a functional over all elements and fold
them together
Examples
iex> fold_map([1, 2, 3], fn x -> [x, x * 10] end)
[1, 10, 2, 20, 3, 30]
iex> fold_map([[1, 2, 3], [4, 5, 6], [7, 8, 9]], fn x -> [x, x] end)
[
[1, 2, 3], [1, 2, 3],
[4, 5, 6], [4, 5, 6],
[7, 8, 9], [7, 8, 9]
]
left_fold(Witchcraft.Foldable.t, (any, any -> any)) :: any
The same as left_fold/3
, but uses the first element as the seed
Examples
iex> left_fold([1, 2, 3], &+/2)
6
iex> left_fold([100, 2, 5], &//2)
10.0 # ((100 / 2) / 5)
iex> left_fold([1, 2, 3], [], fn(acc, x) -> [x | acc] end)
[3, 2, 1]
Note the reducer argument order versus right_fold/2
iex> right_fold([100, 20, 10], &//2)
200.0
iex> left_fold([100, 20, 10], &//2)
0.5
left_fold(Witchcraft.Foldable.t, any, (any, any -> any)) :: any
Left-associative fold over a structure to alter the structure and/or reduce it to a single summary value.
The folder must be a binary function, with the second argument being the accumulated value thus far.
Examples
iex> sum = fn xs -> right_fold(xs, 0, &+/2) end
...> sum.([1, 2, 3])
6
...> sum.([4, 5, 6])
15
iex> left_fold([1, 2, 3], [], fn(acc, x) -> [x | acc] end)
[3, 2, 1]
iex> left_fold({1, 2, 3}, [], fn(acc, x) -> [x | acc] end)
[3]
iex> left_fold([1, 2, 3], [4, 5, 6], fn(acc, x) -> [x | acc] end)
[3, 2, 1, 4, 5, 6]
Note the reducer argument order versus right_fold/3
iex> right_fold([1, 2, 3], [], fn(acc, x) -> [acc | x] end)
[1, 2, 3]
iex> left_fold([1, 2, 3], [], fn(acc, x) -> [acc | x] end)
[[[[] | 1] | 2] | 3]
Count the number of elements in a foldable structure
Examples
iex> use Witchcraft.Foldable
...> length(%{})
0
iex> length(%{a: 1, b: 2})
2
iex> length("ࠀabc")
4
Find the maximum element in a foldable structure using the default ordering
from Witchcraft.Ord
.
Elements must implement Witchcraft.Ord
.
Examples
iex> use Witchcraft.Foldable
...> max([2, 3, 1])
3
...> max([[4], [1, 2, 3, 4]])
[4]
%BinaryTree{
node: 1,
left: %BinaryTree{
node: 3
left: 4
},
right: 2
}
|> max()
#=> 4
max(Witchcraft.Foldable.t, [{:by, (any, any -> Order.ordering)}]) :: Witchcraft.Ord.t
Find the maximum element in a foldable structure using a custom comparitor
Elements must implement Witchcraft.Ord
.
Comes in both a safe and unsafe(!
) version
Examples
iex> use Witchcraft.Foldable
...> [1, 2, 7]
...> |> max(by: fn(x, y) ->
...> x
...> |> Integer.mod(3)
...> |> Witchcraft.Ord.compare(Integer.mod(y, 3))
...> end)
2
member?(Witchcraft.Foldable.t, any) :: boolean
Check if a foldable structure contains a particular element
Examples
iex> member?([1, 2, 3], 2)
true
iex> member?([1, 2, 3], 99)
false
iex> member?(%{a: 1, b: 2}, 2)
true
iex> member?(%{a: 1, b: 2}, 99)
false
Find the minimum element in a foldable structure using the default ordering
from Witchcraft.Ord
.
Elements must implement Witchcraft.Ord
.
Examples
iex> use Witchcraft.Foldable
...> min([2, 3, 1])
1
...> min([[4], [1, 2, 3, 4]])
[1, 2, 3, 4]
%BinaryTree{
node: 4,
left: %BinaryTree{
node: 3
left: 1
},
right: 2
}
|> min()
#=> 1
min(Witchcraft.Foldable.t, [{:by, (any, any -> Order.t)}]) :: any | Maybe.t
Find the maximum element in a foldable structure using a custom comparitor
Elements must implement Witchcraft.Ord
.
Comes in both a safe and unsafe(!
) version
Examples
iex> use Witchcraft.Foldable
...> [8, 2, 1]
...> |> min(by: fn(x, y) ->
...> x
...> |> Integer.mod(4)
...> |> Witchcraft.Ord.compare(Integer.mod(y, 4))
...> end)
8
Test whether the structure is empty. The default implementation is optimized for structures that are similar to lists, because there is no general way to do better.
Examples
iex> null?([])
true
iex> null?([1, 2, 3])
false
Product of all numbers in a foldable
Examples
iex> product([1, 2, 3])
6
iex> product({1, 2, 3})
6
%BinaryTree{
left: 4,
right: %BinaryTree{
left: 2,
right: 10
}
}
|> product()
#=> 80
random(Witchcraft.Foldable.t) :: any | Witchcraft.Foldable.EmptyError.t
Get a random element from a foldable structure.
Examples
random([1, 2, 3])
#=> 1
random([1, 2, 3])
#=> 3
random(%BinaryTree{left: %Empty{}, node: 2, right: %BinaryTree{node: 1}})
1
right_fold(Witchcraft.Foldable.t, (... -> any)) :: any
The same as right_fold/3
, but uses the first element as the seed
Examples
iex> right_fold([1, 2, 3], &+/2)
6
iex> right_fold([100, 2, 5], &//2)
40.0 # (2 / (5 / 100))
iex> right_fold([[], 1, 2, 3], fn(x, acc) -> [x | acc] end)
[1, 2, 3]
right_fold(Witchcraft.Foldable.t, any, (any, any -> any)) :: any
Right-associative fold over a structure to alter the structure and/or reduce it to a single summary value. The right-association makes it possible to cease computation on infinite streams of data.
The folder must be a binary function, with the second argument being the accumulated value thus far.
Examples
iex> sum = fn xs -> right_fold(xs, 0, &+/2) end
...> sum.([1, 2, 3])
6
...> sum.([4, 5, 6])
15
Sum all numbers in a foldable
Examples
iex> sum([1, 2, 3])
6
iex> sum({1, 2, 3})
3
%BinaryTree{
left: 4,
right: %BinaryTree{
left: 2,
right: 10
}
} |> sum()
#=> 16
then_sequence(Witchcraft.Foldable.t) :: Witchcraft.Monad.t
Run each action from left to right, discarding all values.
Always returns %Witchcraft.Unit{}
in the same foldbale structure that you started with.
Examples
iex> then_sequence([[1, 2, 3], [4, 5, 6]])
[
%Witchcraft.Unit{},
%Witchcraft.Unit{},
%Witchcraft.Unit{},
%Witchcraft.Unit{},
%Witchcraft.Unit{},
%Witchcraft.Unit{},
%Witchcraft.Unit{},
%Witchcraft.Unit{},
%Witchcraft.Unit{}
]
iex> then_sequence({{1, 2, 3}, {4, 5, 6}})
{4, 5, %Witchcraft.Unit{}}
iex> then_sequence({[1, 2, 3], [4, 5, 6]})
[
%Witchcraft.Unit{},
%Witchcraft.Unit{},
%Witchcraft.Unit{}
]
The same as then_traverse
, but with the arguments flipped.
Examples
iex> fn x -> [x, x * 5, x * 10] end
...> |> then_through([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{}
]
then_traverse(Witchcraft.Foldable.t, Witchcraft.Apply.fun) :: Witchcraft.Apply.t
then_traverse(Witchcraft.Apply.fun, Witchcraft.Foldable.t) :: Witchcraft.Apply.t
traverse
actions over data, but ignore the results.
Not a typo: this is in the correct module, since it doens’t depend directly
on Witchcraft.Traversable
, but behaves in a similar manner.
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{}
]
Turn any Foldable
into a List
Example
iex> to_list({1, 2, 3})
[1, 2, 3]
iex> to_list(%{a: 1, b: 2, c: 3})
[1, 2, 3]