Skip to main content

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::*;