Skip to main content

fp_library/classes/
send_ref_semimonad.rs

1//! Thread-safe by-ref monadic sequencing with [`send_ref_bind`].
2//!
3//! Like [`RefSemimonad::ref_bind`](crate::classes::RefSemimonad::ref_bind), but
4//! the continuation must be `Send` and element types must be `Send + Sync`.
5//!
6//! ### Examples
7//!
8//! ```
9//! use fp_library::{
10//! 	brands::*,
11//! 	classes::*,
12//! 	functions::*,
13//! 	types::*,
14//! };
15//!
16//! let lazy = ArcLazy::new(|| 5);
17//! let result = send_ref_bind::<LazyBrand<ArcLazyConfig>, _, _>(&lazy, |x: &i32| {
18//! 	let v = *x * 2;
19//! 	ArcLazy::new(move || v)
20//! });
21//! assert_eq!(*result.evaluate(), 10);
22//! ```
23
24#[fp_macros::document_module]
25mod inner {
26	use {
27		crate::kinds::*,
28		fp_macros::*,
29	};
30
31	/// A type class for thread-safe monadic sequencing via references.
32	///
33	/// This is the thread-safe counterpart of [`RefSemimonad`](crate::classes::RefSemimonad).
34	#[kind(type Of<'a, A: 'a>: 'a;)]
35	pub trait SendRefSemimonad {
36		/// Sequences a thread-safe computation using a reference to the value.
37		#[document_signature]
38		///
39		#[document_type_parameters(
40			"The lifetime of the values.",
41			"The type of the value inside the context.",
42			"The type of the value in the resulting context."
43		)]
44		///
45		#[document_parameters(
46			"The context containing the value.",
47			"A thread-safe function that receives a reference to the value and returns a new context."
48		)]
49		///
50		#[document_returns("A new context produced by the function.")]
51		#[document_examples]
52		///
53		/// ```
54		/// use fp_library::{
55		/// 	brands::*,
56		/// 	classes::*,
57		/// 	types::*,
58		/// };
59		///
60		/// let lazy = ArcLazy::new(|| 5);
61		/// let result = LazyBrand::<ArcLazyConfig>::send_ref_bind(&lazy, |x: &i32| {
62		/// 	let v = *x * 2;
63		/// 	ArcLazy::new(move || v)
64		/// });
65		/// assert_eq!(*result.evaluate(), 10);
66		/// ```
67		fn send_ref_bind<'a, A: Send + Sync + 'a, B: Send + Sync + 'a>(
68			ma: &Apply!(<Self as Kind!( type Of<'a, T: 'a>: 'a; )>::Of<'a, A>),
69			f: impl Fn(&A) -> Apply!(<Self as Kind!( type Of<'a, T: 'a>: 'a; )>::Of<'a, B>) + Send + 'a,
70		) -> Apply!(<Self as Kind!( type Of<'a, T: 'a>: 'a; )>::Of<'a, B>);
71	}
72
73	/// Sequences a thread-safe computation using a reference to the value.
74	///
75	/// Free function version that dispatches to [the type class' associated function][`SendRefSemimonad::send_ref_bind`].
76	#[document_signature]
77	///
78	#[document_type_parameters(
79		"The lifetime of the values.",
80		"The brand of the context.",
81		"The type of the value inside the context.",
82		"The type of the value in the resulting context."
83	)]
84	///
85	#[document_parameters(
86		"The context containing the value.",
87		"A thread-safe function that receives a reference to the value and returns a new context."
88	)]
89	///
90	#[document_returns("A new context produced by the function.")]
91	#[document_examples]
92	///
93	/// ```
94	/// use fp_library::{
95	/// 	brands::*,
96	/// 	functions::*,
97	/// 	types::*,
98	/// };
99	///
100	/// let lazy = ArcLazy::new(|| 5);
101	/// let result = send_ref_bind::<LazyBrand<ArcLazyConfig>, _, _>(&lazy, |x: &i32| {
102	/// 	let v = *x * 2;
103	/// 	ArcLazy::new(move || v)
104	/// });
105	/// assert_eq!(*result.evaluate(), 10);
106	/// ```
107	pub fn send_ref_bind<'a, Brand: SendRefSemimonad, A: Send + Sync + 'a, B: Send + Sync + 'a>(
108		ma: &Apply!(<Brand as Kind!( type Of<'a, T: 'a>: 'a; )>::Of<'a, A>),
109		f: impl Fn(&A) -> Apply!(<Brand as Kind!( type Of<'a, T: 'a>: 'a; )>::Of<'a, B>) + Send + 'a,
110	) -> Apply!(<Brand as Kind!( type Of<'a, T: 'a>: 'a; )>::Of<'a, B>) {
111		Brand::send_ref_bind(ma, f)
112	}
113}
114
115pub use inner::*;