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}