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