fp_library/classes/apply_second.rs
1//! A type class for sequencing two computations and keeping the result of the second.
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_second::<OptionBrand, _, _>(x, y);
11//! assert_eq!(z, Some(10));
12//! ```
13
14use super::lift::Lift;
15use crate::{Apply, kinds::*};
16
17/// A type class for types that support combining two contexts, keeping the second value.
18///
19/// `ApplySecond` provides the ability to sequence two computations but discard
20/// the result of the first computation, keeping only the result of the second.
21pub trait ApplySecond: Lift {
22 /// Combines two contexts, keeping the value from the second context.
23 ///
24 /// This function sequences two computations and discards the result of the first computation, keeping only the result of the second.
25 ///
26 /// ### Type Signature
27 ///
28 /// `forall a b. ApplySecond f => (f a, f b) -> f b`
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 second 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_second::<OptionBrand, _, _>(x, y);
52 /// assert_eq!(z, Some(10));
53 /// ```
54 fn apply_second<'a, B: 'a + Clone, A: '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, B>) {
58 Self::lift2::<B, A, B, _>(|_, b| b, fa, fb)
59 }
60}
61
62/// Combines two contexts, keeping the value from the second context.
63///
64/// Free function version that dispatches to [the type class' associated function][`ApplySecond::apply_second`].
65///
66/// ### Type Signature
67///
68/// `forall a b. ApplySecond f => (f a, f b) -> f b`
69///
70/// ### Type Parameters
71///
72/// * `Brand`: The brand of the context.
73/// * `B`: The type of the value in the second context.
74/// * `A`: The type of the value in the first context.
75///
76/// ### Parameters
77///
78/// * `fa`: The first context.
79/// * `fb`: The second context.
80///
81/// ### Returns
82///
83/// The second 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_second::<OptionBrand, _, _>(x, y);
93/// assert_eq!(z, Some(10));
94/// ```
95pub fn apply_second<'a, Brand: ApplySecond, B: 'a + Clone, A: '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, B>) {
99 Brand::apply_second::<B, A>(fa, fb)
100}