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