Skip to main content

fp_library/classes/
apply_first.rs

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