Skip to main content

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}