Skip to main content

fp_library/classes/
ref_functor.rs

1//! Types that can be mapped over by receiving or returning references to their contents.
2//!
3//! ### Examples
4//!
5//! ```
6//! use fp_library::{
7//! 	brands::*,
8//! 	functions::*,
9//! 	types::*,
10//! };
11//!
12//! let memo = Lazy::<_, RcLazyConfig>::new(|| 10);
13//! let mapped = ref_map::<LazyBrand<RcLazyConfig>, _, _>(|x: &i32| *x * 2, memo);
14//! assert_eq!(*mapped.evaluate(), 20);
15//! ```
16
17#[fp_macros::document_module]
18mod inner {
19	use {
20		crate::kinds::*,
21		fp_macros::*,
22	};
23
24	/// A type class for types that can be mapped over, returning references.
25	///
26	/// This is a variant of `Functor` for types where `map` receives/returns references.
27	/// This is required for types like `Lazy` where `get()` returns `&A`, not `A`.
28	pub trait RefFunctor: Kind_cdc7cd43dac7585f {
29		/// Maps a function over the values in the functor context, where the function takes a reference.
30		#[document_signature]
31		///
32		#[document_type_parameters(
33			"The lifetime of the values.",
34			"The type of the value(s) inside the functor.",
35			"The type of the result(s) of applying the function."
36		)]
37		///
38		#[document_parameters(
39			"The function to apply to the value(s) inside the functor.",
40			"The functor instance containing the value(s)."
41		)]
42		///
43		#[document_returns(
44			"A new functor instance containing the result(s) of applying the function."
45		)]
46		#[document_examples]
47		///
48		/// ```
49		/// use fp_library::{
50		/// 	brands::*,
51		/// 	classes::*,
52		/// 	types::*,
53		/// };
54		///
55		/// let memo = Lazy::<_, RcLazyConfig>::new(|| 10);
56		/// let mapped = LazyBrand::<RcLazyConfig>::ref_map(|x: &i32| *x * 2, memo);
57		/// assert_eq!(*mapped.evaluate(), 20);
58		/// ```
59		fn ref_map<'a, A: 'a, B: 'a>(
60			func: impl FnOnce(&A) -> B + 'a,
61			fa: Apply!(<Self as Kind!( type Of<'a, T: 'a>: 'a; )>::Of<'a, A>),
62		) -> Apply!(<Self as Kind!( type Of<'a, T: 'a>: 'a; )>::Of<'a, B>);
63	}
64
65	/// Maps a function over the values in the functor context, where the function takes a reference.
66	///
67	/// Free function version that dispatches to [the type class' associated function][`RefFunctor::ref_map`].
68	#[document_signature]
69	///
70	#[document_type_parameters(
71		"The lifetime of the values.",
72		"The brand of the functor.",
73		"The type of the value(s) inside the functor.",
74		"The type of the result(s) of applying the function."
75	)]
76	///
77	#[document_parameters(
78		"The function to apply to the value(s) inside the functor.",
79		"The functor instance containing the value(s)."
80	)]
81	///
82	#[document_returns("A new functor instance containing the result(s) of applying the function.")]
83	#[document_examples]
84	///
85	/// ```
86	/// use fp_library::{
87	/// 	brands::*,
88	/// 	functions::*,
89	/// 	types::*,
90	/// };
91	///
92	/// let memo = Lazy::<_, RcLazyConfig>::new(|| 10);
93	/// let mapped = ref_map::<LazyBrand<RcLazyConfig>, _, _>(|x: &i32| *x * 2, memo);
94	/// assert_eq!(*mapped.evaluate(), 20);
95	/// ```
96	pub fn ref_map<'a, Brand: RefFunctor, A: 'a, B: 'a>(
97		func: impl FnOnce(&A) -> B + 'a,
98		fa: Apply!(<Brand as Kind!( type Of<'a, T: 'a>: 'a; )>::Of<'a, A>),
99	) -> Apply!(<Brand as Kind!( type Of<'a, T: 'a>: 'a; )>::Of<'a, B>) {
100		Brand::ref_map(func, fa)
101	}
102}
103
104pub use inner::*;