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_c3c3610c70409ee6 {
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!(
54 brand: Self,
55 signature: ('a, A: 'a) -> 'a,
56 ),
57 ) -> Apply!(
58 brand: Self,
59 signature: ('a, B: 'a) -> 'a,
60 )
61 where
62 F: Fn(A) -> B + 'a;
63}
64
65/// Maps a function over the values in the functor context.
66///
67/// Free function version that dispatches to [the type class' associated function][`Functor::map`].
68///
69/// ### Type Signature
70///
71/// `forall a b. Functor f => (a -> b, f a) -> f b`
72///
73/// ### Type Parameters
74///
75/// * `Brand`: The brand of the functor.
76/// * `F`: The type of the function to apply.
77/// * `A`: The type of the value(s) inside the functor.
78/// * `B`: The type of the result(s) of applying the function.
79///
80/// ### Parameters
81///
82/// * `f`: The function to apply to the value(s) inside the functor.
83/// * `fa`: The functor instance containing the value(s).
84///
85/// ### Returns
86///
87/// A new functor instance containing the result(s) of applying the function.
88///
89/// ### Examples
90///
91/// ```
92/// use fp_library::classes::functor::map;
93/// use fp_library::brands::OptionBrand;
94///
95/// let x = Some(5);
96/// let y = map::<OptionBrand, _, _, _>(|i| i * 2, x);
97/// assert_eq!(y, Some(10));
98/// ```
99pub fn map<'a, Brand: Functor, F, A: 'a, B: 'a>(
100 f: F,
101 fa: Apply!(
102 brand: Brand,
103 signature: ('a, A: 'a) -> 'a,
104 ),
105) -> Apply!(
106 brand: Brand,
107 signature: ('a, B: 'a) -> 'a,
108)
109where
110 F: Fn(A) -> B + 'a,
111{
112 Brand::map(f, fa)
113}