deep_causality_haft/algebra/
comonad.rs

1/*
2 * SPDX-License-Identifier: MIT
3 * Copyright (c) "2025" . The DeepCausality Authors and Contributors. All Rights Reserved.
4 */
5use crate::{Functor, HKT};
6use deep_causality_num::Zero;
7
8/// The `CoMonad` trait represents a comonadic context, which is the dual of a `Monad`.
9///
10/// While a `Monad` allows for chaining computations that produce values *within* a context
11/// (e.g., `bind` for `M<A>` to `M<B>`), a `CoMonad` focuses on computations that consume
12/// values *from* a context and produce new contexts based on observations.
13///
14/// Think of a `CoMonad` as a context that can be "inspected" or "observed" to yield a value,
15/// and then "extended" to produce new contexts by applying a function that observes the original context.
16///
17/// It provides two primary operations:
18/// - `extract`: To get the current value at the "focus" of the context.
19/// - `extend`: To create a new comonadic context by applying a function that transforms
20///   the original context itself into a value, which then becomes the content of the new context.
21///
22/// # Intuition & Analogy
23///
24/// A common analogy is a spreadsheet cell:
25/// - `extract` gets the value of the current cell.
26/// - `extend` allows you to fill a new spreadsheet with the results of formulas applied
27///   to the original spreadsheet. Each cell in the new spreadsheet is derived by observing
28///   the context of the old spreadsheet (e.g., the cell itself and its neighbors).
29///
30/// # Laws (Informal)
31///
32/// 1.  **Left Identity**: `extend(w, extract) = w`
33///     (Extending a context with its own `extract` function should yield the original context).
34/// 2.  **Right Identity**: `extract(extend(w, f)) = f(w)`
35///     (Extracting from an extended context should be the same as directly applying the function `f` to the context).
36/// 3.  **Associativity**: `extend(extend(w, f), g) = extend(w, |w_prime| g(extend(w_prime, f)))`
37///     (Extending twice is equivalent to extending once with a composed function).
38///
39/// # Type Parameters
40///
41/// *   `F`: A Higher-Kinded Type (HKT) witness that represents the type constructor
42///     (e.g., `BoxWitness`). This `F` must also be a `Functor`.
43pub trait CoMonad<F: HKT>: Functor<F> {
44    /// Extracts the value at the current focus of the comonadic context.
45    ///
46    /// This operation allows you to "peek inside" the context and obtain its current value
47    /// without transforming the context itself.
48    ///
49    /// # Arguments
50    ///
51    /// *   `fa`: A reference to the comonadic context (`F::Type<A>`).
52    ///
53    /// # Returns
54    ///
55    /// The value `A` contained within the context `fa`.
56    ///
57    /// # Type Parameters
58    ///
59    /// *   `A`: The type of the value to extract.
60    ///
61    /// # Requirements
62    ///
63    /// *   `A: Clone`: The extracted value must be clonable, as `extract` takes a reference
64    ///     and returns an owned value, implying a copy.
65    ///
66    /// # Examples
67    ///
68    /// ```
69    /// use deep_causality_haft::{BoxWitness, CoMonad};
70    ///
71    /// let box_val = Box::new(42);
72    /// let extracted = BoxWitness::extract(&box_val);
73    /// assert_eq!(extracted, 42);
74    /// ```
75    fn extract<A>(fa: &F::Type<A>) -> A
76    where
77        A: Clone;
78
79    /// Extends the comonadic context by applying a function to its observed state.
80    ///
81    /// This creates a new comonadic context `F::Type<B>`, where each element `B` is the
82    /// result of applying the function `f` to the *original* context `fa`.
83    /// The function `f` receives a reference to the `fa` (the original context)
84    /// and should produce a value `B`.
85    ///
86    /// # Arguments
87    ///
88    /// *   `fa`: A reference to the original comonadic context (`F::Type<A>`).
89    /// *   `f`: A function (`Func`) that takes a reference to the context `F::Type<A>`
90    ///     and returns a new value `B`. This function represents an "observation"
91    ///     or "computation" based on the current context.
92    ///
93    /// # Returns
94    ///
95    /// A new comonadic context (`F::Type<B>`) where each element is the result
96    /// of applying `f` to the original context.
97    ///
98    /// # Type Parameters
99    ///
100    /// *   `A`: The type of the values in the original context.
101    /// *   `B`: The type of the values in the new context.
102    /// *   `Func`: The type of the extension function, which must be `FnMut(&F::Type<A>) -> B`.
103    ///
104    /// # Examples
105    ///
106    /// ```
107    /// use deep_causality_haft::{BoxWitness, CoMonad, HKT};
108    ///
109    /// let box_val = Box::new(5);
110    ///
111    /// // Extend to create a new Box containing the square of the original value
112    /// let f_square = |b: &<BoxWitness as HKT>::Type<i32>| (**b) * (**b);
113    /// let extended_square = BoxWitness::extend(&box_val, f_square);
114    /// assert_eq!(extended_square, Box::new(25));
115    ///
116    /// // Extend to create a new Box containing a string representation
117    /// let f_to_string = |b: &<BoxWitness as HKT>::Type<i32>| format!("Value: {}", **b);
118    /// let extended_string = BoxWitness::extend(&box_val, f_to_string);
119    /// assert_eq!(extended_string, Box::new("Value: 5".to_string()));
120    /// ```
121    fn extend<A, B, Func>(fa: &F::Type<A>, f: Func) -> F::Type<B>
122    where
123        Func: FnMut(&F::Type<A>) -> B;
124}
125
126/// A Comonad that requires its contents to satisfy algebraic bounds.
127/// Essential for structures like MultiVectors that need a 'Zero' to represent
128/// a  Physical Field Operator.
129pub trait BoundedComonad<F: HKT>: Functor<F> {
130    fn extract<A>(fa: &F::Type<A>) -> A
131    where
132        A: Clone; // Extract usually requires Clone
133
134    fn extend<A, B, Func>(fa: &F::Type<A>, f: Func) -> F::Type<B>
135    where
136        Func: FnMut(&F::Type<A>) -> B,
137        A: Zero + Copy + Clone,
138        B: Zero + Copy + Clone;
139}