Skip to main content

fp_library/classes/
functor.rs

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