fp_library/classes/
functor.rs

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