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!(
49 brand: Self,
50 signature: ('a, A: 'a) -> 'a,
51 ),
52 fb: Apply!(
53 brand: Self,
54 signature: ('a, B: 'a) -> 'a,
55 ),
56 ) -> Apply!(
57 brand: Self,
58 signature: ('a, A: 'a) -> 'a,
59 ) {
60 Self::lift2(|a, _| a, fa, fb)
61 }
62}
63
64/// Combines two contexts, keeping the value from the first context.
65///
66/// Free function version that dispatches to [the type class' associated function][`ApplyFirst::apply_first`].
67///
68/// ### Type Signature
69///
70/// `forall a b. ApplyFirst f => (f a, f b) -> f a`
71///
72/// ### Type Parameters
73///
74/// * `Brand`: The brand of the context.
75/// * `A`: The type of the value in the first context.
76/// * `B`: The type of the value in the second context.
77///
78/// ### Parameters
79///
80/// * `fa`: The first context.
81/// * `fb`: The second context.
82///
83/// ### Returns
84///
85/// The first context.
86///
87/// ### Examples
88///
89/// ```
90/// use fp_library::classes::apply_first::apply_first;
91/// use fp_library::brands::OptionBrand;
92///
93/// let x = Some(5);
94/// let y = Some(10);
95/// let z = apply_first::<OptionBrand, _, _>(x, y);
96/// assert_eq!(z, Some(5));
97/// ```
98pub fn apply_first<'a, Brand: ApplyFirst, A: 'a + Clone, B: 'a + Clone>(
99 fa: Apply!(
100 brand: Brand,
101 signature: ('a, A: 'a) -> 'a,
102 ),
103 fb: Apply!(
104 brand: Brand,
105 signature: ('a, B: 'a) -> 'a,
106 ),
107) -> Apply!(
108 brand: Brand,
109 signature: ('a, A: 'a) -> 'a,
110) {
111 Brand::apply_first(fa, fb)
112}