fp_library/classes/ref_apply_first.rs
1//! Combining two by-ref contexts, keeping the first value, with [`ref_apply_first`].
2//!
3//! This is the by-ref counterpart of [`ApplyFirst`](crate::classes::ApplyFirst).
4//!
5//! ### Examples
6//!
7//! ```
8//! use fp_library::{
9//! brands::*,
10//! functions::{
11//! explicit::apply_first,
12//! *,
13//! },
14//! types::*,
15//! };
16//!
17//! let x = RcLazy::pure(3);
18//! let y = RcLazy::pure(4);
19//! let result = apply_first::<LazyBrand<RcLazyConfig>, _, _, _, _>(&x, &y);
20//! assert_eq!(*result.evaluate(), 3);
21//! ```
22
23#[fp_macros::document_module]
24mod inner {
25 use {
26 crate::kinds::*,
27 fp_macros::*,
28 };
29
30 /// A type class for combining two by-ref contexts, keeping the first value.
31 ///
32 /// Requires `A: Clone` because the closure receives `&A` and must produce
33 /// an owned `A`. The default implementation uses [`RefLift::ref_lift2`](crate::classes::RefLift::ref_lift2).
34 #[kind(type Of<'a, A: 'a>: 'a;)]
35 pub trait RefApplyFirst: crate::classes::RefLift {
36 /// Combines two contexts, keeping the value from the first.
37 #[document_signature]
38 ///
39 #[document_type_parameters(
40 "The lifetime of the values.",
41 "The type of the value in the first context. Must be `Clone`.",
42 "The type of the value in the second context."
43 )]
44 ///
45 #[document_parameters("The first context.", "The second context.")]
46 ///
47 #[document_returns("A new context containing the value from the first context.")]
48 #[document_examples]
49 ///
50 /// ```
51 /// use fp_library::{
52 /// brands::*,
53 /// classes::*,
54 /// types::*,
55 /// };
56 ///
57 /// let x = RcLazy::pure(3);
58 /// let y = RcLazy::pure(4);
59 /// let result = LazyBrand::<RcLazyConfig>::ref_apply_first(&x, &y);
60 /// assert_eq!(*result.evaluate(), 3);
61 /// ```
62 fn ref_apply_first<'a, A: Clone + 'a, B: 'a>(
63 fa: &Apply!(<Self as Kind!( type Of<'a, T: 'a>: 'a; )>::Of<'a, A>),
64 fb: &Apply!(<Self as Kind!( type Of<'a, T: 'a>: 'a; )>::Of<'a, B>),
65 ) -> Apply!(<Self as Kind!( type Of<'a, T: 'a>: 'a; )>::Of<'a, A>) {
66 Self::ref_lift2(|a: &A, _: &B| a.clone(), fa, fb)
67 }
68 }
69
70 /// Blanket implementation of [`RefApplyFirst`].
71 #[document_type_parameters("The brand type.")]
72 impl<Brand: crate::classes::RefLift> RefApplyFirst for Brand {}
73
74 /// Combines two contexts, keeping the value from the first.
75 ///
76 /// Free function version that dispatches to [the type class' associated function][`RefApplyFirst::ref_apply_first`].
77 #[document_signature]
78 ///
79 #[document_type_parameters(
80 "The lifetime of the values.",
81 "The brand of the context.",
82 "The type of the value in the first context. Must be `Clone`.",
83 "The type of the value in the second context."
84 )]
85 ///
86 #[document_parameters("The first context.", "The second context.")]
87 ///
88 #[document_returns("A new context containing the value from the first context.")]
89 #[document_examples]
90 ///
91 /// ```
92 /// use fp_library::{
93 /// brands::*,
94 /// functions::{
95 /// explicit::apply_first,
96 /// *,
97 /// },
98 /// types::*,
99 /// };
100 ///
101 /// let x = RcLazy::pure(3);
102 /// let y = RcLazy::pure(4);
103 /// let result = apply_first::<LazyBrand<RcLazyConfig>, _, _, _, _>(&x, &y);
104 /// assert_eq!(*result.evaluate(), 3);
105 /// ```
106 pub fn ref_apply_first<'a, Brand: RefApplyFirst, A: Clone + 'a, B: 'a>(
107 fa: &Apply!(<Brand as Kind!( type Of<'a, T: 'a>: 'a; )>::Of<'a, A>),
108 fb: &Apply!(<Brand as Kind!( type Of<'a, T: 'a>: 'a; )>::Of<'a, B>),
109 ) -> Apply!(<Brand as Kind!( type Of<'a, T: 'a>: 'a; )>::Of<'a, A>) {
110 Brand::ref_apply_first(fa, fb)
111 }
112}
113
114pub use inner::*;