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//!
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_first::<OptionBrand, _, _>(x, y);
14//! assert_eq!(z, Some(5));
15//! ```
16
17use super::lift::Lift;
18use crate::{Apply, kinds::*};
19
20/// A type class for types that support combining two contexts, keeping the first value.
21///
22/// `ApplyFirst` provides the ability to sequence two computations but discard
23/// the result of the second computation, keeping only the result of the first.
24pub trait ApplyFirst: Lift {
25	/// Combines two contexts, keeping the value from the first context.
26	///
27	/// This function sequences two computations and discards the result of the second computation, keeping only the result of the first.
28	///
29	/// ### Type Signature
30	///
31	/// `forall a b. ApplyFirst f => (f a, f b) -> f a`
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 first 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_first::<OptionBrand, _, _>(x, y);
55	/// assert_eq!(z, Some(5));
56	/// ```
57	fn apply_first<'a, A: 'a + Clone, B: '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, A>) {
61		Self::lift2(|a, _| a, fa, fb)
62	}
63}
64
65/// Combines two contexts, keeping the value from the first context.
66///
67/// Free function version that dispatches to [the type class' associated function][`ApplyFirst::apply_first`].
68///
69/// ### Type Signature
70///
71/// `forall a b. ApplyFirst f => (f a, f b) -> f a`
72///
73/// ### Type Parameters
74///
75/// * `Brand`: The brand of the context.
76/// * `A`: The type of the value in the first context.
77/// * `B`: The type of the value in the second context.
78///
79/// ### Parameters
80///
81/// * `fa`: The first context.
82/// * `fb`: The second context.
83///
84/// ### Returns
85///
86/// The first 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_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!(<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, A>) {
102	Brand::apply_first(fa, fb)
103}