fp_library/classes/functor.rs
1use crate::{Apply, kinds::*};
2
3/// A type class 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/// `Functor` instances must satisfy the following laws:
11/// * Identity: `map(identity, fa) = fa`.
12/// * Composition: `map(compose(f, g), fa) = map(f, map(g, fa))`.
13pub trait Functor: Kind_c3c3610c70409ee6 {
14 /// Maps a function over the values in the functor context.
15 ///
16 /// # Type Signature
17 ///
18 /// `forall a b. Functor f => (a -> b, f a) -> f b`
19 ///
20 /// # Parameters
21 ///
22 /// * `f`: The function to apply to the value(s) inside the functor.
23 /// * `fa`: The functor instance containing the value(s).
24 ///
25 /// # Returns
26 ///
27 /// A new functor instance containing the result(s) of applying the function.
28 ///
29 /// # Examples
30 ///
31 /// ```
32 /// use fp_library::classes::functor::Functor;
33 /// use fp_library::brands::OptionBrand;
34 ///
35 /// let x = Some(5);
36 /// let y = OptionBrand::map(|i| i * 2, x);
37 /// assert_eq!(y, Some(10));
38 /// ```
39 fn map<'a, A: 'a, B: 'a, F>(
40 f: F,
41 fa: Apply!(
42 brand: Self,
43 signature: ('a, A: 'a) -> 'a,
44 ),
45 ) -> Apply!(
46 brand: Self,
47 signature: ('a, B: 'a) -> 'a,
48 )
49 where
50 F: Fn(A) -> B + 'a;
51}
52
53/// Maps a function over the values in the functor context.
54///
55/// Free function version that dispatches to [the type class' associated function][`Functor::map`].
56///
57/// # Type Signature
58///
59/// `forall a b. Functor f => (a -> b, f a) -> f b`
60///
61/// # Parameters
62///
63/// * `f`: The function to apply to the value(s) inside the functor.
64/// * `fa`: The functor instance containing the value(s).
65///
66/// # Returns
67///
68/// A new functor instance containing the result(s) of applying the function.
69///
70/// # Examples
71///
72/// ```
73/// use fp_library::classes::functor::map;
74/// use fp_library::brands::OptionBrand;
75///
76/// let x = Some(5);
77/// let y = map::<OptionBrand, _, _, _>(|i| i * 2, x);
78/// assert_eq!(y, Some(10));
79/// ```
80pub fn map<'a, Brand: Functor, A: 'a, B: 'a, F>(
81 f: F,
82 fa: Apply!(
83 brand: Brand,
84 signature: ('a, A: 'a) -> 'a,
85 ),
86) -> Apply!(
87 brand: Brand,
88 signature: ('a, B: 'a) -> 'a,
89)
90where
91 F: Fn(A) -> B + 'a,
92{
93 Brand::map(f, fa)
94}