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/// # Parameters
40///
41/// * `fa`: The first context containing a value (will be discarded).
42/// * `fb`: The second context containing a value.
43///
44/// # Returns
45///
46/// The second context with its value preserved.
47///
48/// # Examples
49///
50/// ```
51/// use fp_library::{brands::OptionBrand, functions::apply_second};
52///
53/// assert_eq!(apply_second::<OptionBrand, _, _>(Some(5))(Some("hello")), Some("hello"));
54/// ```
55pub fn apply_second<Brand, A, B>(
56	fa: Apply<Brand, (A,)>
57) -> impl Fn(Apply<Brand, (B,)>) -> Apply<Brand, (B,)>
58where
59	Brand: Kind<(A,)> + Kind<(B,)> + ApplySecond,
60	Apply<Brand, (A,)>: Clone,
61	B: Clone,
62{
63	Brand::apply_second::<A, B>(fa)
64}