pub trait SendRefFunctor: Kind_cdc7cd43dac7585f {
// Required method
fn send_ref_map<'a, A: Send + Sync + 'a, B: Send + Sync + 'a>(
func: impl FnOnce(&A) -> B + Send + 'a,
fa: <Self as Kind_cdc7cd43dac7585f>::Of<'a, A>,
) -> <Self as Kind_cdc7cd43dac7585f>::Of<'a, B>;
}Expand description
A type class for types that can be mapped over, receiving references, with thread-safe functions.
This is a variant of RefFunctor where the mapping function
must be Send, making it suitable for thread-safe lazy types like
ArcLazy.
§Why a Separate Trait?
A single trait with Send bounds on RefFunctor would exclude RcLazy, which uses
Rc (a !Send type). By keeping RefFunctor free of Send bounds and providing
SendRefFunctor separately, RcLazy can implement RefFunctor while ArcLazy
implements only SendRefFunctor.
§Laws
SendRefFunctor instances must satisfy the following laws:
- Identity:
send_ref_map(|x| x.clone(), fa)evaluates to a value equal tofa’s evaluated value. - Composition:
send_ref_map(|x| f(&g(x)), fa)evaluates to the same value assend_ref_map(f, send_ref_map(g, fa)).
§Examples
SendRefFunctor laws for ArcLazy:
use fp_library::{
brands::*,
functions::*,
types::*,
};
// Identity: send_ref_map(|x| x.clone(), fa) evaluates to the same value as fa.
let fa = ArcLazy::pure(5);
let mapped = send_ref_map::<LazyBrand<ArcLazyConfig>, _, _>(|x: &i32| *x, fa.clone());
assert_eq!(*mapped.evaluate(), *fa.evaluate());
// Composition: send_ref_map(|x| f(&g(x)), fa) = send_ref_map(f, send_ref_map(g, fa))
let f = |x: &i32| x + 1;
let g = |x: &i32| *x * 2;
let fa = ArcLazy::pure(5);
let composed = send_ref_map::<LazyBrand<ArcLazyConfig>, _, _>(|x: &i32| f(&g(x)), fa.clone());
let sequential = send_ref_map::<LazyBrand<ArcLazyConfig>, _, _>(
f,
send_ref_map::<LazyBrand<ArcLazyConfig>, _, _>(g, fa),
);
assert_eq!(*composed.evaluate(), *sequential.evaluate());§Cache chain behavior
Chaining send_ref_map calls on memoized types like ArcLazy
creates a linked list of Arc-referenced cells. Each mapped value retains a reference to
its predecessor, so the entire chain of predecessor cells stays alive as long as any
downstream mapped value is reachable. Be aware that long chains can accumulate memory
that is only freed when the final value in the chain is dropped.
§Why FnOnce?
The func parameter uses FnOnce rather than Fn because memoized types like
ArcLazy create a new ArcLazy value capturing the closure. Since the resulting
ArcLazy will evaluate the closure at most once, FnOnce is sufficient and avoids
imposing unnecessary Clone or multi-call constraints on the caller.
Required Methods§
Sourcefn send_ref_map<'a, A: Send + Sync + 'a, B: Send + Sync + 'a>(
func: impl FnOnce(&A) -> B + Send + 'a,
fa: <Self as Kind_cdc7cd43dac7585f>::Of<'a, A>,
) -> <Self as Kind_cdc7cd43dac7585f>::Of<'a, B>
fn send_ref_map<'a, A: Send + Sync + 'a, B: Send + Sync + 'a>( func: impl FnOnce(&A) -> B + Send + 'a, fa: <Self as Kind_cdc7cd43dac7585f>::Of<'a, A>, ) -> <Self as Kind_cdc7cd43dac7585f>::Of<'a, B>
Maps a thread-safe function over the values in the functor context, where the function takes a reference.
§Type Signature
forall A B. (&A -> B, Self A) -> Self B
§Type Parameters
'a: The lifetime of the values.A: The type of the value(s) inside the functor.B: The type of the result(s) of applying the function.
§Parameters
func: The function to apply to the value(s) inside the functor.fa: The functor instance containing the value(s).
§Returns
A new functor instance containing the result(s) of applying the function.
§Examples
use fp_library::{
brands::*,
classes::*,
types::*,
};
let memo = ArcLazy::new(|| 10);
let mapped = LazyBrand::<ArcLazyConfig>::send_ref_map(|x: &i32| *x * 2, memo);
assert_eq!(*mapped.evaluate(), 20);Dyn Compatibility§
This trait is not dyn compatible.
In older versions of Rust, dyn compatibility was called "object safety", so this trait is not object safe.
Implementors§
impl SendRefFunctor for LazyBrand<ArcLazyConfig>
impl<E: 'static + Clone + Send + Sync> SendRefFunctor for TryLazyBrand<E, ArcLazyConfig>
§Type Parameters
E: The type of the error.