Skip to main content

RefFunctor

Trait RefFunctor 

Source
pub trait RefFunctor: Kind_cdc7cd43dac7585f {
    // Required method
    fn ref_map<'a, A: 'a, B: 'a>(
        func: impl FnOnce(&A) -> B + '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, returning references.

This is a variant of Functor for types where map receives/returns references. This is required for types like Lazy where get() returns &A, not A.

RefFunctor is intentionally independent from SendRefFunctor. Although one might expect SendRefFunctor to be a subtrait of RefFunctor, this is not the case because ArcLazy::new requires Send on the closure, which a generic RefFunctor cannot guarantee. As a result, ArcLazy implements only SendRefFunctor, not RefFunctor, and RcLazy implements only RefFunctor, not SendRefFunctor.

§Laws

RefFunctor instances must satisfy the following laws:

Identity: ref_map(|x| x.clone(), fa) is equivalent to fa, given A: Clone. The Clone requirement arises because the mapping function receives &A but must produce a value of type A to satisfy the identity law.

Composition: ref_map(|x| g(&f(x)), fa) is equivalent to ref_map(g, ref_map(f, fa)).

§Examples

RefFunctor laws for Lazy:

use fp_library::{
	brands::*,
	functions::*,
	types::*,
};

// Identity: ref_map(|x| x.clone(), fa) evaluates to the same value as fa.
let fa = RcLazy::pure(5);
let mapped = ref_map::<LazyBrand<RcLazyConfig>, _, _>(|x: &i32| *x, fa.clone());
assert_eq!(*mapped.evaluate(), *fa.evaluate());

// Composition: ref_map(|x| g(&f(x)), fa) = ref_map(g, ref_map(f, fa))
let f = |x: &i32| *x * 2;
let g = |x: &i32| x + 1;
let fa = RcLazy::pure(5);
let composed = ref_map::<LazyBrand<RcLazyConfig>, _, _>(|x: &i32| g(&f(x)), fa.clone());
let sequential = ref_map::<LazyBrand<RcLazyConfig>, _, _>(
	g,
	ref_map::<LazyBrand<RcLazyConfig>, _, _>(f, fa),
);
assert_eq!(*composed.evaluate(), *sequential.evaluate());

§Cache chain behavior

Chaining ref_map calls on memoized types like Lazy creates a linked list of Rc/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 Lazy create a new Lazy value capturing the closure. Since the resulting Lazy will evaluate the closure at most once, FnOnce is sufficient and avoids imposing unnecessary Clone or multi-call constraints on the caller.

Required Methods§

Source

fn ref_map<'a, A: 'a, B: 'a>( func: impl FnOnce(&A) -> B + 'a, fa: <Self as Kind_cdc7cd43dac7585f>::Of<'a, A>, ) -> <Self as Kind_cdc7cd43dac7585f>::Of<'a, B>

Maps a 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 = Lazy::<_, RcLazyConfig>::new(|| 10);
let mapped = LazyBrand::<RcLazyConfig>::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§

Source§

impl RefFunctor for LazyBrand<RcLazyConfig>

Source§

impl<E: 'static + Clone> RefFunctor for TryLazyBrand<E, RcLazyConfig>

§Type Parameters
  • E: The type of the error.