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