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