fp_library/classes/send_ref_semiapplicative.rs
1//! Thread-safe by-ref function application within contexts with [`send_ref_apply`].
2//!
3//! Like [`RefSemiapplicative::ref_apply`](crate::classes::RefSemiapplicative::ref_apply),
4//! but uses [`SendCloneFn<Ref>`](crate::classes::SendCloneFn) for thread-safe
5//! function wrappers and requires element types to be `Send + Sync`.
6//!
7//! ### Examples
8//!
9//! ```
10//! use fp_library::{
11//! brands::*,
12//! classes::*,
13//! functions::*,
14//! types::*,
15//! };
16//!
17//! let f = ArcLazy::new(|| {
18//! std::sync::Arc::new(|x: &i32| *x * 2) as std::sync::Arc<dyn Fn(&i32) -> i32 + Send + Sync>
19//! });
20//! let x = ArcLazy::new(|| 5);
21//! let result = send_ref_apply::<ArcFnBrand, LazyBrand<ArcLazyConfig>, _, _>(&f, &x);
22//! assert_eq!(*result.evaluate(), 10);
23//! ```
24
25#[fp_macros::document_module]
26mod inner {
27 use {
28 crate::{
29 classes::*,
30 dispatch::Ref,
31 kinds::*,
32 },
33 fp_macros::*,
34 };
35
36 /// A type class for applying wrapped thread-safe by-ref functions within contexts.
37 ///
38 /// The wrapped functions have type `Fn(&A) -> B + Send + Sync` (via
39 /// [`SendCloneFn<Ref>`]). No `Clone` bound on `A` is needed; the
40 /// function receives a reference and produces an owned result.
41 ///
42 /// This is the thread-safe counterpart of [`RefSemiapplicative`].
43 #[kind(type Of<'a, A: 'a>: 'a;)]
44 pub trait SendRefSemiapplicative: SendRefLift + SendRefFunctor {
45 /// Applies a wrapped thread-safe by-ref function to a value within a context.
46 #[document_signature]
47 ///
48 #[document_type_parameters(
49 "The lifetime of the values.",
50 "The brand of the thread-safe cloneable function wrapper.",
51 "The type of the input value.",
52 "The type of the output value."
53 )]
54 ///
55 #[document_parameters(
56 "The context containing the wrapped thread-safe by-ref function.",
57 "The context containing the value."
58 )]
59 ///
60 #[document_returns("A new context containing the result of applying the function.")]
61 #[document_examples]
62 ///
63 /// ```
64 /// use fp_library::{
65 /// brands::*,
66 /// classes::*,
67 /// types::*,
68 /// };
69 ///
70 /// let f = ArcLazy::new(|| {
71 /// std::sync::Arc::new(|x: &i32| *x * 2) as std::sync::Arc<dyn Fn(&i32) -> i32 + Send + Sync>
72 /// });
73 /// let x = ArcLazy::new(|| 5);
74 /// let result = LazyBrand::<ArcLazyConfig>::send_ref_apply::<ArcFnBrand, _, _>(&f, &x);
75 /// assert_eq!(*result.evaluate(), 10);
76 /// ```
77 fn send_ref_apply<
78 'a,
79 FnBrand: 'a + SendCloneFn<Ref>,
80 A: Send + Sync + 'a,
81 B: Send + Sync + 'a,
82 >(
83 ff: &Apply!(<Self as Kind!( type Of<'a, T: 'a>: 'a; )>::Of<'a, <FnBrand as SendCloneFn<Ref>>::Of<'a, A, B>>),
84 fa: &Apply!(<Self as Kind!( type Of<'a, T: 'a>: 'a; )>::Of<'a, A>),
85 ) -> Apply!(<Self as Kind!( type Of<'a, T: 'a>: 'a; )>::Of<'a, B>);
86 }
87
88 /// Applies a wrapped thread-safe by-ref function to a value within a context.
89 ///
90 /// Free function version that dispatches to [the type class' associated function][`SendRefSemiapplicative::send_ref_apply`].
91 #[document_signature]
92 ///
93 #[document_type_parameters(
94 "The lifetime of the values.",
95 "The brand of the thread-safe cloneable function wrapper.",
96 "The brand of the context.",
97 "The type of the input value.",
98 "The type of the output value."
99 )]
100 ///
101 #[document_parameters(
102 "The context containing the wrapped thread-safe by-ref function.",
103 "The context containing the value."
104 )]
105 ///
106 #[document_returns("A new context containing the result of applying the function.")]
107 #[document_examples]
108 ///
109 /// ```
110 /// use fp_library::{
111 /// brands::*,
112 /// functions::*,
113 /// types::*,
114 /// };
115 ///
116 /// let f = ArcLazy::new(|| {
117 /// std::sync::Arc::new(|x: &i32| *x * 2) as std::sync::Arc<dyn Fn(&i32) -> i32 + Send + Sync>
118 /// });
119 /// let x = ArcLazy::new(|| 5);
120 /// let result = send_ref_apply::<ArcFnBrand, LazyBrand<ArcLazyConfig>, _, _>(&f, &x);
121 /// assert_eq!(*result.evaluate(), 10);
122 /// ```
123 pub fn send_ref_apply<
124 'a,
125 FnBrand: 'a + SendCloneFn<Ref>,
126 Brand: SendRefSemiapplicative,
127 A: Send + Sync + 'a,
128 B: Send + Sync + 'a,
129 >(
130 ff: &Apply!(<Brand as Kind!( type Of<'a, T: 'a>: 'a; )>::Of<'a, <FnBrand as SendCloneFn<Ref>>::Of<'a, A, B>>),
131 fa: &Apply!(<Brand as Kind!( type Of<'a, T: 'a>: 'a; )>::Of<'a, A>),
132 ) -> Apply!(<Brand as Kind!( type Of<'a, T: 'a>: 'a; )>::Of<'a, B>) {
133 Brand::send_ref_apply::<FnBrand, A, B>(ff, fa)
134 }
135}
136
137pub use inner::*;