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}