fp_library/typeclasses/apply_first.rs
1use crate::{
2 hkt::{Apply0L1T, Kind0L1T},
3 typeclasses::{ClonableFn, clonable_fn::ApplyFn},
4};
5
6/// A typeclass for types that support combining two contexts, keeping the first value.
7///
8/// `ApplyFirst` provides the ability to sequence two computations but discard
9/// the result of the second computation, keeping only the result of the first.
10/// This is useful for executing side effects in sequence while preserving the
11/// primary result.
12pub trait ApplyFirst: Kind0L1T {
13 /// Combines two contexts, keeping the value from the first context.
14 ///
15 /// # Type Signature
16 ///
17 /// `forall f a b. ApplyFirst f => f a -> f b -> f a`
18 ///
19 /// # Parameters
20 ///
21 /// * `fa`: The first context containing a value.
22 /// * `fb`: The second context containing a value (will be discarded).
23 ///
24 /// # Returns
25 ///
26 /// The first context with its value preserved.
27 fn apply_first<'a, ClonableFnBrand: 'a + ClonableFn, A: 'a + Clone, B>(
28 fa: Apply0L1T<Self, A>
29 ) -> ApplyFn<'a, ClonableFnBrand, Apply0L1T<Self, B>, Apply0L1T<Self, A>>;
30}
31
32/// Combines two contexts, keeping the value from the first context.
33///
34/// Free function version that dispatches to [the typeclass' associated function][`ApplyFirst::apply_first`].
35///
36/// # Type Signature
37///
38/// `forall f a b. ApplyFirst f => f a -> f b -> f a`
39///
40/// # Parameters
41///
42/// * `fa`: The first context containing a value.
43/// * `fb`: The second context containing a value (will be discarded).
44///
45/// # Returns
46///
47/// The first context with its value preserved.
48///
49/// # Examples
50///
51/// ```
52/// use fp_library::{brands::{OptionBrand, RcFnBrand}, functions::apply_first};
53///
54/// assert_eq!(apply_first::<RcFnBrand, OptionBrand, _, _>(Some(5))(Some("hello")), Some(5));
55/// ```
56pub fn apply_first<'a, ClonableFnBrand: 'a + ClonableFn, Brand: ApplyFirst, A: 'a + Clone, B>(
57 fa: Apply0L1T<Brand, A>
58) -> ApplyFn<'a, ClonableFnBrand, Apply0L1T<Brand, B>, Apply0L1T<Brand, A>> {
59 Brand::apply_first::<ClonableFnBrand, A, B>(fa)
60}