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}