deep_causality_haft/foldable.rs
1/*
2 * SPDX-License-Identifier: MIT
3 * Copyright (c) "2025" . The DeepCausality Authors and Contributors. All Rights Reserved.
4 */
5use crate::HKT;
6
7/// The `Foldable` trait abstracts over data structures that can be reduced to a single summary value.
8///
9/// It provides a `fold` operation (also known as `reduce` or `inject`) that applies a binary function
10/// to an accumulator and each element of the structure, from left to right.
11///
12/// This trait is generic over `F`, which is a Higher-Kinded Type (HKT) witness.
13///
14/// # Laws (Informal)
15///
16/// 1. **Fold right equivalence**: `foldr f z t = foldl (flip f) z (reverse t)` (if `reverse` is defined)
17/// 2. **Fold identity**: `fold f z (pure x) = f z x` (if `pure` is defined)
18///
19/// # Type Parameters
20///
21/// * `F`: A Higher-Kinded Type (HKT) witness that represents the type constructor
22/// (e.g., `OptionWitness`, `ResultWitness<E>`, `VecWitness`).
23pub trait Foldable<F: HKT> {
24 /// Reduces the elements of the structure to a single value by applying a function.
25 ///
26 /// This is equivalent to a left-fold (`foldl`) operation. It traverses the structure,
27 /// applying the `f` function to an accumulating value and each element.
28 ///
29 /// # Arguments
30 ///
31 /// * `fa`: The data structure (`F::Type<A>`) to fold.
32 /// * `init`: The initial value of the accumulator.
33 /// * `f`: A binary function that takes the current accumulator and an element
34 /// from the structure, and returns the new accumulator value.
35 ///
36 /// # Returns
37 ///
38 /// The final accumulated value after processing all elements.
39 ///
40 /// # Type Parameters
41 ///
42 /// * `A`: The type of the elements within the foldable structure.
43 /// * `B`: The type of the accumulator and the final result.
44 /// * `Func`: The type of the folding function, which must be `FnMut(B, A) -> B`.
45 ///
46 /// # Examples
47 ///
48 /// ```
49 /// use deep_causality_haft::{Foldable, OptionWitness};
50 ///
51 /// let opt = Some(5);
52 /// let sum = OptionWitness::fold(opt, 0, |acc, x| acc + x);
53 /// assert_eq!(sum, 5);
54 ///
55 /// let none_opt: Option<i32> = None;
56 /// let sum_none = OptionWitness::fold(none_opt, 0, |acc, x| acc + x);
57 /// assert_eq!(sum_none, 0);
58 /// ```
59 fn fold<A, B, Func>(fa: F::Type<A>, init: B, f: Func) -> B
60 where
61 Func: FnMut(B, A) -> B;
62}