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