Current section

Files

Jump to
funx lib foldable.ex
Raw

lib/foldable.ex

defprotocol Funx.Foldable do
@moduledoc """
[![Run in Livebook](https://livebook.dev/badge/v1/black.svg)](https://livebook.dev/run?url=https%3A%2F%2Fgithub.com%2FJKWA%2Ffunx%2Fblob%2Fmain%2Flivebooks%2Ffoldable%2Ffoldable.livemd)
The `Funx.Foldable` protocol defines two core folding operations: `fold_l/3` (fold left) and `fold_r/3` (fold right).
These functions allow structures to be collapsed into a single value by applying functions in a specific order.
Depending on the structure, folding can be done from the left (`fold_l/3`) or from the right (`fold_r/3`).
"""
@doc """
Folds the structure from the left, applying `func_a` if a condition is met, otherwise applying `func_b`.
This function collapses a structure by recursively applying the provided functions from the leftmost element to the rightmost.
## Parameters:
- `structure`: The structure to fold.
- `func_a`: The function to apply in case of a matching condition.
- `func_b`: The function to apply if the condition is not met.
## Examples
iex> Funx.Foldable.fold_l(Funx.Monad.Maybe.just(5), fn x -> x + 1 end, fn -> 0 end)
6
iex> Funx.Foldable.fold_l(Funx.Monad.Maybe.nothing(), fn _ -> 1 end, fn -> 0 end)
0
"""
def fold_l(structure, func_a, func_b)
@doc """
Folds the structure from the right, applying `func_a` if a condition is met, otherwise applying `func_b`.
This function collapses a structure by recursively applying the provided functions from the rightmost element to the leftmost.
## Parameters:
- `structure`: The structure to fold.
- `func_a`: The function to apply in case of a matching condition.
- `func_b`: The function to apply if the condition is not met.
## Examples
iex> Funx.Foldable.fold_r(Funx.Monad.Maybe.just(5), fn x -> x + 1 end, fn -> 0 end)
6
iex> Funx.Foldable.fold_r(Funx.Monad.Maybe.nothing(), fn _ -> 1 end, fn -> 0 end)
0
"""
def fold_r(structure, func_a, func_b)
end
defimpl Funx.Foldable, for: Function do
@moduledoc """
Provides an implementation of the `Funx.Foldable` protocol for functions (predicates).
This implementation evaluates a predicate function and applies either `true_func` or `false_func` based on the result.
Useful for folding over boolean predicates, collapsing them into a single result.
"""
@doc """
Folds a predicate function from the left.
The predicate is evaluated, and if it returns `true`, the `true_func` is applied; otherwise, the `false_func` is applied.
## Examples
iex> Funx.Foldable.fold_l(fn -> true end, fn -> "True case" end, fn -> "False case" end)
"True case"
iex> Funx.Foldable.fold_l(fn -> false end, fn -> "True case" end, fn -> "False case" end)
"False case"
"""
def fold_l(predicate, true_func, false_func) do
case predicate.() do
true -> true_func.()
false -> false_func.()
end
end
@doc """
Folds a predicate function from the right.
The predicate is evaluated, and if it returns `true`, the `true_func` is applied; otherwise, the `false_func` is applied.
## Examples
iex> Funx.Foldable.fold_r(fn -> true end, fn -> "True case" end, fn -> "False case" end)
"True case"
iex> Funx.Foldable.fold_r(fn -> false end, fn -> "True case" end, fn -> "False case" end)
"False case"
"""
def fold_r(predicate, true_func, false_func), do: fold_l(predicate, true_func, false_func)
end