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}