1
2
3
4
5
6
7
8
9
10
11
12
13
14
15
16
17
18
19
20
21
22
23
24
25
26
27
28
29
30
31
32
33
34
35
36
37
38
39
40
41
42
43
44
45
46
47
48
49
50
51
52
53
54
55
56
57
58
59
60
61
62
63
64
65
66
67
68
69
70
71
72
73
74
75
76
77
78
79
80
81
82
83
84
85
86
87
88
89
90
91
92
93
94
95
96
97
98
99
100
101
102
103
104
105
106
107
108
109
110
111
112
113
114
115
116
117
118
pub mod hkt {
//! # Higher-Kinded Type (HKT) Functor
//!
//! This module defines the `Functor` trait for types that implement the HKT pattern.
//! A Functor is a type constructor `F` that supports a `map` operation, allowing
//! a function `A -> B` to be applied to a value(s) within a structure `F<A>`,
//! resulting in a structure `F<B>`.
//!
//! The HKT `Functor` trait is generic over:
//! - `Self`: The HKT marker (e.g., [`OptionHKTMarker`]).
//! - `A`: The input type of the value(s) within the HKT structure.
//! - `B`: The output type after applying the mapping function.
//!
//! It relies on the [`HKT1`] trait from `crate::kind_based::kind` to relate the
//! marker `Self` to its concrete type application `Self::Applied<T>`.
use crate::kind_based::kind::{HKT1, OptionHKTMarker, ResultHKTMarker, VecHKTMarker, CFnHKTMarker, CFnOnceHKTMarker};
use crate::function::{CFn, CFnOnce};
/// Represents a type constructor that can be mapped over, using the HKT pattern.
///
/// `Self` refers to the HKT marker type (e.g., [`OptionHKTMarker`], [`VecHKTMarker`])
/// that implements [`HKT1`].
///
/// The `map` operation takes an instance of `Self::Applied<A>` (e.g., `Option<A>`)
/// and a function `A -> B`, producing `Self::Applied<B>` (e.g., `Option<B>`).
///
/// ## Functor Laws
/// Implementors must satisfy two laws:
/// 1. **Identity**: For any HKT marker `F` and value `x: F::Applied<A>`,
/// `F::map(x, |a| a) == x`.
/// 2. **Composition**: For any HKT marker `F`, value `x: F::Applied<A>`, and functions
/// `f: A -> B`, `g: B -> C`,
/// `F::map(F::map(x, f), g) == F::map(x, |a| g(f(a)))`.
pub trait Functor<A, B>: HKT1 { // A is input type, B is output type for map
/// Applies a function to a value (or values) within an HKT-encoded structure.
///
/// # Type Parameters
/// - `Self`: The HKT marker (e.g., [`OptionHKTMarker`]).
/// - `A`: The type of the value(s) inside the input structure `Self::Applied<A>`.
/// - `B`: The type of the value(s) inside the output structure `Self::Applied<B>`.
///
/// # Parameters
/// - `input`: The HKT-structured value, e.g., `Option<A>`, `Vec<A>`.
/// - `func`: A function to apply to the inner value(s).
/// The `FnMut(A) -> B + Clone + 'static` bound is chosen for broad compatibility:
/// - `FnMut`: Allows mutation of captured state if needed, and covers `Fn` and `FnOnce`
/// that don't consume their captures by value on first call. Standard library `map`
/// methods (like `Option::map`, `Result::map`) often take `FnOnce`.
/// - `Clone`: Necessary for some implementations like [`CFnHKTMarker`], where the
/// function might need to be cloned if the resulting structure can be "called"
/// multiple times.
/// - `'static`: Often required when functions are stored or returned within structures
/// like [`CFn`] or [`CFnOnce`], especially if they don't borrow from the local scope.
///
/// # Returns
/// A new HKT-structured value `Self::Applied<B>` containing the result(s) of
/// applying `func`.
fn map(input: Self::Applied<A>, func: impl FnMut(A) -> B + Clone + 'static) -> Self::Applied<B>;
}
impl<A, B> Functor<A, B> for OptionHKTMarker {
fn map(input: Self::Applied<A>, func: impl FnMut(A) -> B + Clone + 'static) -> Self::Applied<B> {
input.map(func) // Option::map takes FnOnce, FnMut is compatible
}
}
impl<A, B, E> Functor<A, B> for ResultHKTMarker<E> {
fn map(input: Self::Applied<A>, func: impl FnMut(A) -> B + Clone + 'static) -> Self::Applied<B> {
input.map(func) // Result::map takes FnOnce, FnMut is compatible
}
}
impl<A, B> Functor<A, B> for VecHKTMarker {
fn map(input: Self::Applied<A>, func: impl FnMut(A) -> B + Clone + 'static) -> Self::Applied<B> {
input.into_iter().map(func).collect()
}
}
// Functor impl for CFnHKTMarker (maps over the output type of CFn)
// A is the original output type, B is the new output type
impl<X, A, B> Functor<A, B> for CFnHKTMarker<X>
where
X: 'static,
A: 'static,
B: 'static, // B must be 'static for CFn<X,B> which is Self::Applied<B>
{
fn map(input: Self::Applied<A>, func: impl FnMut(A) -> B + Clone + 'static) -> Self::Applied<B>
{
// input is CFn<X, A>
// func is A -> B
// result is CFn<X, B>
// To create a new CFn, the captured 'func' needs to be Clone if 'input' is called multiple times.
// Or, if 'input' is Fn, and 'func' is Fn, the result can be Fn.
// Let's assume func is Clone for simplicity to create a new CFn.
CFn::new(move |x: X| func.clone()(input.call(x))) // func.clone() for new CFn
}
}
// Functor impl for CFnOnceHKTMarker (maps over the output type of CFnOnce)
impl<X, A, B> Functor<A, B> for CFnOnceHKTMarker<X>
where
X: 'static,
A: 'static,
B: 'static, // B must be 'static for CFnOnce<X,B> which is Self::Applied<B>
{
fn map(input: Self::Applied<A>, mut func: impl FnMut(A) -> B + Clone + 'static) -> Self::Applied<B> // Added mut for func
{
CFnOnce::new(move |x: X| func(input.call_once(x)))
}
}
}
// Directly export HKT Functor
pub use hkt::{Functor};
// Note: CFnHKTMarker and CFnOnceHKTMarker are defined in kind_based::kind
// and Functor implementations for them are in the hkt module above.
// This re-export makes `crate::functor::Functor` point to the HKT one.