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}