fp_library/classes/
functor.rs

1//! Functor type class.
2//!
3//! This module defines the [`Functor`] trait, which represents types that can be mapped over.
4
5use crate::{Apply, kinds::*};
6
7/// A type class for types that can be mapped over.
8///
9/// A `Functor` represents a context or container that allows functions to be applied
10/// to values within that context without altering the structure of the context itself.
11///
12/// ### Laws
13///
14/// `Functor` instances must satisfy the following laws:
15/// * Identity: `map(identity, fa) = fa`.
16/// * Composition: `map(compose(f, g), fa) = map(f, map(g, fa))`.
17pub trait Functor: Kind_cdc7cd43dac7585f {
18	/// Maps a function over the values in the functor context.
19	///
20	/// This method applies a function to the value(s) inside the functor context, producing a new functor context with the transformed value(s).
21	///
22	/// ### Type Signature
23	///
24	/// `forall a b. Functor f => (a -> b, f a) -> f b`
25	///
26	/// ### Type Parameters
27	///
28	/// * `F`: The type of the function to apply.
29	/// * `A`: The type of the value(s) inside the functor.
30	/// * `B`: The type of the result(s) of applying the function.
31	///
32	/// ### Parameters
33	///
34	/// * `f`: The function to apply to the value(s) inside the functor.
35	/// * `fa`: The functor instance containing the value(s).
36	///
37	/// ### Returns
38	///
39	/// A new functor instance containing the result(s) of applying the function.
40	///
41	/// ### Examples
42	///
43	/// ```
44	/// use fp_library::classes::functor::Functor;
45	/// use fp_library::brands::OptionBrand;
46	///
47	/// let x = Some(5);
48	/// let y = OptionBrand::map(|i| i * 2, x);
49	/// assert_eq!(y, Some(10));
50	/// ```
51	fn map<'a, F, A: 'a, B: 'a>(
52		f: F,
53		fa: Apply!(<Self as Kind!( type Of<'a, T: 'a>: 'a; )>::Of<'a, A>),
54	) -> Apply!(<Self as Kind!( type Of<'a, T: 'a>: 'a; )>::Of<'a, B>)
55	where
56		F: Fn(A) -> B + 'a;
57}
58
59/// Maps a function over the values in the functor context.
60///
61/// Free function version that dispatches to [the type class' associated function][`Functor::map`].
62///
63/// ### Type Signature
64///
65/// `forall a b. Functor f => (a -> b, f a) -> f b`
66///
67/// ### Type Parameters
68///
69/// * `Brand`: The brand of the functor.
70/// * `F`: The type of the function to apply.
71/// * `A`: The type of the value(s) inside the functor.
72/// * `B`: The type of the result(s) of applying the function.
73///
74/// ### Parameters
75///
76/// * `f`: The function to apply to the value(s) inside the functor.
77/// * `fa`: The functor instance containing the value(s).
78///
79/// ### Returns
80///
81/// A new functor instance containing the result(s) of applying the function.
82///
83/// ### Examples
84///
85/// ```
86/// use fp_library::classes::functor::map;
87/// use fp_library::brands::OptionBrand;
88///
89/// let x = Some(5);
90/// let y = map::<OptionBrand, _, _, _>(|i| i * 2, x);
91/// assert_eq!(y, Some(10));
92/// ```
93pub fn map<'a, Brand: Functor, F, A: 'a, B: 'a>(
94	f: F,
95	fa: Apply!(<Brand as Kind!( type Of<'a, T: 'a>: 'a; )>::Of<'a, A>),
96) -> Apply!(<Brand as Kind!( type Of<'a, T: 'a>: 'a; )>::Of<'a, B>)
97where
98	F: Fn(A) -> B + 'a,
99{
100	Brand::map(f, fa)
101}