Skip to main content

ParFoldable

Trait ParFoldable 

Source
pub trait ParFoldable: Foldable {
    // Required method
    fn par_fold_map<'a, FnBrand, A, M>(
        func: <FnBrand as SendCloneableFn>::SendOf<'a, A, M>,
        fa: <Self as Kind_cdc7cd43dac7585f>::Of<'a, A>,
    ) -> M
       where FnBrand: 'a + SendCloneableFn,
             A: 'a + Clone + Send + Sync,
             M: Monoid + Send + Sync + 'a;

    // Provided method
    fn par_fold_right<'a, FnBrand, A, B>(
        func: <FnBrand as SendCloneableFn>::SendOf<'a, (A, B), B>,
        init: B,
        fa: <Self as Kind_cdc7cd43dac7585f>::Of<'a, A>,
    ) -> B
       where A: 'a + Clone + Send + Sync,
             B: Send + Sync + 'a,
             FnBrand: 'a + SendCloneableFn { ... }
}
Expand description

A type class for data structures that can be folded in parallel.

This trait provides parallel versions of Foldable operations that require Send + Sync bounds on elements and functions. It uses the branded SendOf function type to maintain the library’s HKT abstraction.

Note: The rayon feature must be enabled to use parallel iteration.

§Minimal Implementation

A minimal implementation requires ParFoldable::par_fold_map.

§Thread Safety

All operations in this trait are designed to be safe for parallel execution:

  • Element type A must be Send + Sync
  • Accumulator/result types must be Send + Sync
  • Functions are wrapped in FnBrand::SendOf which guarantees Send + Sync

§Why is FnBrand a Trait-Level Parameter?

Unlike Foldable where FnBrand is a method-level generic parameter and functions are raw Fn types wrapped internally, ParFoldable takes FnBrand at the trait level. This design choice is motivated by:

  1. Thread-safe function values as first-class HKT types: Function parameters like func in ParFoldable::par_fold_map are HKT-applied types via Apply!(brand: FnBrand, kind: SendCloneableFn, output: SendOf, ...). This allows the type system to enforce thread-safety at the API boundary.

  2. Guaranteed Send + Sync bounds: The output: SendOf in the Apply! macro ensures the function type carries Send + Sync bounds essential for parallel execution, rather than relying on runtime checks.

  3. Default implementation requirements: The default ParFoldable::par_fold_right implementation needs to call <FnBrand as SendCloneableFn>::send_cloneable_fn_new(...) to create new wrapped functions. Having FnBrand at the trait level makes it available throughout the implementation.

  4. Multiple implementations per data structure: With trait-level parameterization, a type can implement ParFoldable<ArcFnBrand> and potentially other function brands, allowing callers to choose the appropriate thread-safe function wrapper.

§Examples

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

let v = vec![1, 2, 3, 4, 5];
let f = send_cloneable_fn_new::<ArcFnBrand, _, _>(|x: i32| x.to_string());
let result: String = par_fold_map::<ArcFnBrand, VecBrand, _, _>(f, v);
assert_eq!(result, "12345");

Required Methods§

Source

fn par_fold_map<'a, FnBrand, A, M>( func: <FnBrand as SendCloneableFn>::SendOf<'a, A, M>, fa: <Self as Kind_cdc7cd43dac7585f>::Of<'a, A>, ) -> M
where FnBrand: 'a + SendCloneableFn, A: 'a + Clone + Send + Sync, M: Monoid + Send + Sync + 'a,

Parallel version of fold_map.

Maps each element to a monoid value using func, then combines all values using the monoid’s append operation. The mapping operations may be executed in parallel.

§Type Signature

forall self a m. (ParFoldable self, Monoid m) => (a -> m, self a) -> m

§Type Parameters
  • 'a: The lifetime of the computation.
  • FnBrand: The brand of thread-safe function to use.
  • A: The element type.
  • M: The monoid type.
§Parameters
  • func: The thread-safe function to map each element to a monoid`.
  • fa: The foldable structure.
§Returns

The combined monoid value

§Examples
use fp_library::{brands::*, functions::*};

let v = vec![1, 2, 3, 4, 5];
let f = send_cloneable_fn_new::<ArcFnBrand, _, _>(|x: i32| x.to_string());
let result: String = par_fold_map::<ArcFnBrand, VecBrand, _, _>(f, v);
assert_eq!(result, "12345");

Provided Methods§

Source

fn par_fold_right<'a, FnBrand, A, B>( func: <FnBrand as SendCloneableFn>::SendOf<'a, (A, B), B>, init: B, fa: <Self as Kind_cdc7cd43dac7585f>::Of<'a, A>, ) -> B
where A: 'a + Clone + Send + Sync, B: Send + Sync + 'a, FnBrand: 'a + SendCloneableFn,

Parallel version of fold_right.

Folds the structure by applying a function from right to left, potentially in parallel.

§Type Signature

forall self a b. ParFoldable self => ((a, b) -> b, b, self a) -> b

§Type Parameters
  • 'a: The lifetime of the computation.
  • FnBrand: The brand of thread-safe function to use.
  • A: The element type.
  • B: The accumulator type.
§Parameters
  • func: The thread-safe function to apply to each element and the accumulator.
  • init: The initial value of the accumulator.
  • fa: The structure to fold.
§Returns

The final accumulator value

§Examples
use fp_library::{brands::*, functions::*};

let v = vec![1, 2, 3, 4, 5];
let f = send_cloneable_fn_new::<ArcFnBrand, _, _>(|(a, b)| a + b);
let sum = par_fold_right::<ArcFnBrand, VecBrand, _, _>(f, 10, v);
assert_eq!(sum, 25);

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 ParFoldable for CatListBrand

Source§

impl ParFoldable for IdentityBrand

Source§

impl ParFoldable for OptionBrand

Source§

impl ParFoldable for VecBrand

Source§

impl<DoneType: 'static> ParFoldable for StepWithDoneBrand<DoneType>

Source§

impl<E: 'static> ParFoldable for ResultWithErrBrand<E>

Source§

impl<First: 'static> ParFoldable for PairWithFirstBrand<First>

Source§

impl<LoopType: 'static> ParFoldable for StepWithLoopBrand<LoopType>

Source§

impl<Second: 'static> ParFoldable for PairWithSecondBrand<Second>

Source§

impl<T: 'static> ParFoldable for ResultWithOkBrand<T>