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