fp_library/classes/
apply_first.rs

1use super::lift::Lift;
2use crate::{Apply, kinds::*};
3
4/// A type class for types that support combining two contexts, keeping the first value.
5///
6/// `ApplyFirst` provides the ability to sequence two computations but discard
7/// the result of the second computation, keeping only the result of the first.
8pub trait ApplyFirst: Lift {
9	/// Combines two contexts, keeping the value from the first context.
10	///
11	/// # Type Signature
12	///
13	/// `forall a b. ApplyFirst f => (f a, f b) -> f a`
14	///
15	/// # Parameters
16	///
17	/// * `fa`: The first context.
18	/// * `fb`: The second context.
19	///
20	/// # Returns
21	///
22	/// The first context.
23	///
24	/// # Examples
25	///
26	/// ```
27	/// use fp_library::classes::apply_first::ApplyFirst;
28	/// use fp_library::brands::OptionBrand;
29	///
30	/// let x = Some(5);
31	/// let y = Some(10);
32	/// let z = OptionBrand::apply_first(x, y);
33	/// assert_eq!(z, Some(5));
34	/// ```
35	fn apply_first<'a, A: 'a + Clone, B: 'a + Clone>(
36		fa: Apply!(
37			brand: Self,
38			signature: ('a, A: 'a) -> 'a,
39		),
40		fb: Apply!(
41			brand: Self,
42			signature: ('a, B: 'a) -> 'a,
43		),
44	) -> Apply!(
45		brand: Self,
46		signature: ('a, A: 'a) -> 'a,
47	) {
48		Self::lift2(|a, _| a, fa, fb)
49	}
50}
51
52/// Combines two contexts, keeping the value from the first context.
53///
54/// Free function version that dispatches to [the type class' associated function][`ApplyFirst::apply_first`].
55///
56/// # Type Signature
57///
58/// `forall a b. ApplyFirst f => (f a, f b) -> f a`
59///
60/// # Parameters
61///
62/// * `fa`: The first context.
63/// * `fb`: The second context.
64///
65/// # Returns
66///
67/// The first context.
68///
69/// # Examples
70///
71/// ```
72/// use fp_library::classes::apply_first::apply_first;
73/// use fp_library::brands::OptionBrand;
74///
75/// let x = Some(5);
76/// let y = Some(10);
77/// let z = apply_first::<OptionBrand, _, _>(x, y);
78/// assert_eq!(z, Some(5));
79/// ```
80pub fn apply_first<'a, Brand: ApplyFirst, A: 'a + Clone, B: 'a + Clone>(
81	fa: Apply!(
82		brand: Brand,
83		signature: ('a, A: 'a) -> 'a,
84	),
85	fb: Apply!(
86		brand: Brand,
87		signature: ('a, B: 'a) -> 'a,
88	),
89) -> Apply!(
90	brand: Brand,
91	signature: ('a, A: 'a) -> 'a,
92) {
93	Brand::apply_first(fa, fb)
94}