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
//! Thread-safe by-ref monads, combining [`SendRefApplicative`](crate::classes::SendRefApplicative) and [`SendRefSemimonad`](crate::classes::SendRefSemimonad).
//!
//! This is the thread-safe counterpart of [`RefMonad`](crate::classes::RefMonad).
#[fp_macros::document_module]
mod inner {
use {
crate::classes::*,
fp_macros::*,
};
/// A type that supports thread-safe by-ref function application, pure value
/// injection, and monadic sequencing via references.
///
/// This is the thread-safe counterpart of [`RefMonad`].
/// Automatically implemented for any type implementing both
/// [`SendRefApplicative`] and [`SendRefSemimonad`].
///
/// A lawful `SendRefMonad` must satisfy the same three monad laws as
/// [`RefMonad`], with equality by evaluated value:
///
/// 1. **Left identity**: `send_ref_bind(send_ref_pure(&a), f)` evaluates
/// to the same value as `f(&a)`.
/// 2. **Right identity**: `send_ref_bind(m, |x| send_ref_pure(x))` evaluates
/// to the same value as `m`.
/// 3. **Associativity**: `send_ref_bind(send_ref_bind(m, f), g)` evaluates
/// to the same value as `send_ref_bind(m, |x| send_ref_bind(f(x), g))`.
#[document_examples]
///
/// ```
/// use fp_library::{
/// brands::*,
/// classes::*,
/// functions::*,
/// types::*,
/// };
///
/// let f = |x: &i32| {
/// let v = *x + 1;
/// ArcLazy::new(move || v)
/// };
/// let g = |x: &i32| {
/// let v = *x * 2;
/// ArcLazy::new(move || v)
/// };
///
/// // Left identity
/// let left = send_ref_bind::<LazyBrand<ArcLazyConfig>, _, _>(
/// &send_ref_pure::<LazyBrand<ArcLazyConfig>, _>(&5),
/// f,
/// );
/// assert_eq!(*left.evaluate(), *f(&5).evaluate());
///
/// // Right identity
/// let m = ArcLazy::new(|| 42);
/// let right = send_ref_bind::<LazyBrand<ArcLazyConfig>, _, _>(&m.clone(), |x: &i32| {
/// send_ref_pure::<LazyBrand<ArcLazyConfig>, _>(x)
/// });
/// assert_eq!(*right.evaluate(), *m.evaluate());
///
/// // Associativity
/// let m = ArcLazy::new(|| 3);
/// let lhs = send_ref_bind::<LazyBrand<ArcLazyConfig>, _, _>(
/// &send_ref_bind::<LazyBrand<ArcLazyConfig>, _, _>(&m.clone(), f),
/// g,
/// );
/// let rhs = send_ref_bind::<LazyBrand<ArcLazyConfig>, _, _>(&m, |x: &i32| {
/// send_ref_bind::<LazyBrand<ArcLazyConfig>, _, _>(&f(x), g)
/// });
/// assert_eq!(*lhs.evaluate(), *rhs.evaluate());
/// ```
pub trait SendRefMonad: SendRefApplicative + SendRefSemimonad {}
/// Blanket implementation of [`SendRefMonad`].
#[document_type_parameters("The brand type.")]
impl<Brand> SendRefMonad for Brand where Brand: SendRefApplicative + SendRefSemimonad {}
}
pub use inner::*;