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