fp_library/classes/send_ref_monad.rs
1//! Thread-safe by-ref monads, combining [`SendRefApplicative`](crate::classes::SendRefApplicative) and [`SendRefSemimonad`](crate::classes::SendRefSemimonad).
2//!
3//! This is the thread-safe counterpart of [`RefMonad`](crate::classes::RefMonad).
4
5#[fp_macros::document_module]
6mod inner {
7 use {
8 crate::classes::*,
9 fp_macros::*,
10 };
11
12 /// A type that supports thread-safe by-ref function application, pure value
13 /// injection, and monadic sequencing via references.
14 ///
15 /// This is the thread-safe counterpart of [`RefMonad`].
16 /// Automatically implemented for any type implementing both
17 /// [`SendRefApplicative`] and [`SendRefSemimonad`].
18 ///
19 /// A lawful `SendRefMonad` must satisfy the same three monad laws as
20 /// [`RefMonad`], with equality by evaluated value:
21 ///
22 /// 1. **Left identity**: `send_ref_bind(send_ref_pure(&a), f)` evaluates
23 /// to the same value as `f(&a)`.
24 /// 2. **Right identity**: `send_ref_bind(m, |x| send_ref_pure(x))` evaluates
25 /// to the same value as `m`.
26 /// 3. **Associativity**: `send_ref_bind(send_ref_bind(m, f), g)` evaluates
27 /// to the same value as `send_ref_bind(m, |x| send_ref_bind(f(x), g))`.
28 #[document_examples]
29 ///
30 /// ```
31 /// use fp_library::{
32 /// brands::*,
33 /// classes::*,
34 /// functions::*,
35 /// types::*,
36 /// };
37 ///
38 /// let f = |x: &i32| {
39 /// let v = *x + 1;
40 /// ArcLazy::new(move || v)
41 /// };
42 /// let g = |x: &i32| {
43 /// let v = *x * 2;
44 /// ArcLazy::new(move || v)
45 /// };
46 ///
47 /// // Left identity
48 /// let left = send_ref_bind::<LazyBrand<ArcLazyConfig>, _, _>(
49 /// &send_ref_pure::<LazyBrand<ArcLazyConfig>, _>(&5),
50 /// f,
51 /// );
52 /// assert_eq!(*left.evaluate(), *f(&5).evaluate());
53 ///
54 /// // Right identity
55 /// let m = ArcLazy::new(|| 42);
56 /// let right = send_ref_bind::<LazyBrand<ArcLazyConfig>, _, _>(&m.clone(), |x: &i32| {
57 /// send_ref_pure::<LazyBrand<ArcLazyConfig>, _>(x)
58 /// });
59 /// assert_eq!(*right.evaluate(), *m.evaluate());
60 ///
61 /// // Associativity
62 /// let m = ArcLazy::new(|| 3);
63 /// let lhs = send_ref_bind::<LazyBrand<ArcLazyConfig>, _, _>(
64 /// &send_ref_bind::<LazyBrand<ArcLazyConfig>, _, _>(&m.clone(), f),
65 /// g,
66 /// );
67 /// let rhs = send_ref_bind::<LazyBrand<ArcLazyConfig>, _, _>(&m, |x: &i32| {
68 /// send_ref_bind::<LazyBrand<ArcLazyConfig>, _, _>(&f(x), g)
69 /// });
70 /// assert_eq!(*lhs.evaluate(), *rhs.evaluate());
71 /// ```
72 pub trait SendRefMonad: SendRefApplicative + SendRefSemimonad {}
73
74 /// Blanket implementation of [`SendRefMonad`].
75 #[document_type_parameters("The brand type.")]
76 impl<Brand> SendRefMonad for Brand where Brand: SendRefApplicative + SendRefSemimonad {}
77}
78
79pub use inner::*;