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}