Skip to main content

fp_library/classes/
ref_apply_first.rs

1//! Combining two by-ref contexts, keeping the first value, with [`ref_apply_first`].
2//!
3//! This is the by-ref counterpart of [`ApplyFirst`](crate::classes::ApplyFirst).
4//!
5//! ### Examples
6//!
7//! ```
8//! use fp_library::{
9//! 	brands::*,
10//! 	functions::{
11//! 		explicit::apply_first,
12//! 		*,
13//! 	},
14//! 	types::*,
15//! };
16//!
17//! let x = RcLazy::pure(3);
18//! let y = RcLazy::pure(4);
19//! let result = apply_first::<LazyBrand<RcLazyConfig>, _, _, _, _>(&x, &y);
20//! assert_eq!(*result.evaluate(), 3);
21//! ```
22
23#[fp_macros::document_module]
24mod inner {
25	use {
26		crate::kinds::*,
27		fp_macros::*,
28	};
29
30	/// A type class for combining two by-ref contexts, keeping the first value.
31	///
32	/// Requires `A: Clone` because the closure receives `&A` and must produce
33	/// an owned `A`. The default implementation uses [`RefLift::ref_lift2`](crate::classes::RefLift::ref_lift2).
34	#[kind(type Of<'a, A: 'a>: 'a;)]
35	pub trait RefApplyFirst: crate::classes::RefLift {
36		/// Combines two contexts, keeping the value from the first.
37		#[document_signature]
38		///
39		#[document_type_parameters(
40			"The lifetime of the values.",
41			"The type of the value in the first context. Must be `Clone`.",
42			"The type of the value in the second context."
43		)]
44		///
45		#[document_parameters("The first context.", "The second context.")]
46		///
47		#[document_returns("A new context containing the value from the first context.")]
48		#[document_examples]
49		///
50		/// ```
51		/// use fp_library::{
52		/// 	brands::*,
53		/// 	classes::*,
54		/// 	types::*,
55		/// };
56		///
57		/// let x = RcLazy::pure(3);
58		/// let y = RcLazy::pure(4);
59		/// let result = LazyBrand::<RcLazyConfig>::ref_apply_first(&x, &y);
60		/// assert_eq!(*result.evaluate(), 3);
61		/// ```
62		fn ref_apply_first<'a, A: Clone + 'a, B: 'a>(
63			fa: &Apply!(<Self as Kind!( type Of<'a, T: 'a>: 'a; )>::Of<'a, A>),
64			fb: &Apply!(<Self as Kind!( type Of<'a, T: 'a>: 'a; )>::Of<'a, B>),
65		) -> Apply!(<Self as Kind!( type Of<'a, T: 'a>: 'a; )>::Of<'a, A>) {
66			Self::ref_lift2(|a: &A, _: &B| a.clone(), fa, fb)
67		}
68	}
69
70	/// Blanket implementation of [`RefApplyFirst`].
71	#[document_type_parameters("The brand type.")]
72	impl<Brand: crate::classes::RefLift> RefApplyFirst for Brand {}
73
74	/// Combines two contexts, keeping the value from the first.
75	///
76	/// Free function version that dispatches to [the type class' associated function][`RefApplyFirst::ref_apply_first`].
77	#[document_signature]
78	///
79	#[document_type_parameters(
80		"The lifetime of the values.",
81		"The brand of the context.",
82		"The type of the value in the first context. Must be `Clone`.",
83		"The type of the value in the second context."
84	)]
85	///
86	#[document_parameters("The first context.", "The second context.")]
87	///
88	#[document_returns("A new context containing the value from the first context.")]
89	#[document_examples]
90	///
91	/// ```
92	/// use fp_library::{
93	/// 	brands::*,
94	/// 	functions::{
95	/// 		explicit::apply_first,
96	/// 		*,
97	/// 	},
98	/// 	types::*,
99	/// };
100	///
101	/// let x = RcLazy::pure(3);
102	/// let y = RcLazy::pure(4);
103	/// let result = apply_first::<LazyBrand<RcLazyConfig>, _, _, _, _>(&x, &y);
104	/// assert_eq!(*result.evaluate(), 3);
105	/// ```
106	pub fn ref_apply_first<'a, Brand: RefApplyFirst, A: Clone + 'a, B: 'a>(
107		fa: &Apply!(<Brand as Kind!( type Of<'a, T: 'a>: 'a; )>::Of<'a, A>),
108		fb: &Apply!(<Brand as Kind!( type Of<'a, T: 'a>: 'a; )>::Of<'a, B>),
109	) -> Apply!(<Brand as Kind!( type Of<'a, T: 'a>: 'a; )>::Of<'a, A>) {
110		Brand::ref_apply_first(fa, fb)
111	}
112}
113
114pub use inner::*;