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