fp_library/typeclasses/
functor.rs

1use crate::hkt::{Apply, Kind};
2
3/// A typeclass for types that can be mapped over.
4///
5/// A `Functor` represents a context or container that allows functions to be applied
6/// to values within that context without altering the structure of the context itself.
7///
8/// # Laws
9///
10/// Functors must satisfy the following laws:
11/// * Identity: `map(identity) = identity`.
12/// * Composition: `map(f . g) = map(f) . map(g)`.
13pub trait Functor {
14	/// Maps a function over the values in the functor context.
15	///
16	/// # Type Signature
17	///
18	/// `forall f a b. Functor f => (a -> b) -> f a -> f b`
19	///
20	/// # Parameters
21	///
22	/// * `f`: A function to apply to the values within the functor context.
23	/// * `fa`: A functor containing values of type `A`.
24	///
25	/// # Returns
26	///
27	/// A functor containing values of type `B`.
28	fn map<F, A, B>(f: F) -> impl Fn(Apply<Self, (A,)>) -> Apply<Self, (B,)>
29	where
30		Self: Kind<(A,)> + Kind<(B,)>,
31		F: Fn(A) -> B;
32}
33
34/// Maps a function over the values in the functor context.
35///
36/// Free function version that dispatches to [the typeclass method][`Functor::map`].
37///
38/// # Type Signature
39///
40/// `forall f a b. Functor f => (a -> b) -> f a -> f b`
41///
42/// # Parameters
43///
44/// * `f`: A function to apply to the values within the functor context.
45/// * `fa`: A functor containing values of type `A`.
46///
47/// # Returns
48///
49/// A functor containing values of type `B`.
50///
51/// # Examples
52///
53/// ```
54/// use fp_library::{brands::OptionBrand, functions::map};
55///
56/// assert_eq!(map::<OptionBrand, _, _, _>(|x: i32| x * 2)(Some(5)), Some(10));
57/// ```
58pub fn map<Brand, F, A, B>(f: F) -> impl Fn(Apply<Brand, (A,)>) -> Apply<Brand, (B,)>
59where
60	Brand: Kind<(A,)> + Kind<(B,)> + Functor,
61	F: Fn(A) -> B,
62{
63	Brand::map(f)
64}