fp_library/classes/par_ref_foldable.rs
1//! Parallel by-reference foldable.
2//!
3//! **User story:** "I want to fold over a collection by reference in parallel."
4//!
5//! ### Examples
6//!
7//! ```
8//! use fp_library::{
9//! brands::VecBrand,
10//! classes::par_ref_foldable::ParRefFoldable,
11//! };
12//!
13//! let v = vec![1, 2, 3];
14//! let result = VecBrand::par_ref_fold_map(|x: &i32| x.to_string(), &v);
15//! assert_eq!(result, "123");
16//! ```
17
18#[fp_macros::document_module]
19mod inner {
20 use {
21 crate::{
22 classes::*,
23 kinds::*,
24 },
25 fp_macros::*,
26 };
27
28 /// Parallel by-reference folding over a structure.
29 ///
30 /// Maps each element by reference to a monoid using a `Send + Sync` function
31 /// and combines the results. When the `rayon` feature is enabled, elements are
32 /// processed across multiple threads.
33 #[kind(type Of<'a, A: 'a>: 'a;)]
34 pub trait ParRefFoldable: RefFoldable {
35 /// Maps each element by reference to a monoid and combines them in parallel.
36 #[document_signature]
37 #[document_type_parameters(
38 "The lifetime of the elements.",
39 "The element type.",
40 "The monoid type."
41 )]
42 #[document_parameters(
43 "The function to map each element reference to a monoid. Must be `Send + Sync`.",
44 "The structure to fold."
45 )]
46 #[document_returns("The combined monoid value.")]
47 #[document_examples]
48 ///
49 /// ```
50 /// use fp_library::{
51 /// brands::VecBrand,
52 /// classes::par_ref_foldable::ParRefFoldable,
53 /// };
54 ///
55 /// let v = vec![1, 2, 3];
56 /// let result = VecBrand::par_ref_fold_map(|x: &i32| x.to_string(), &v);
57 /// assert_eq!(result, "123");
58 /// ```
59 fn par_ref_fold_map<'a, A: Send + Sync + 'a, M: Monoid + Send + 'a>(
60 f: impl Fn(&A) -> M + Send + Sync + 'a,
61 fa: &Self::Of<'a, A>,
62 ) -> M;
63 }
64
65 /// Maps each element by reference to a monoid and combines them in parallel.
66 ///
67 /// Free function version that dispatches to [the type class' associated function][`ParRefFoldable::par_ref_fold_map`].
68 #[document_signature]
69 #[document_type_parameters(
70 "The lifetime of the elements.",
71 "The brand of the structure.",
72 "The element type.",
73 "The monoid type."
74 )]
75 #[document_parameters(
76 "The function to map each element reference to a monoid. Must be `Send + Sync`.",
77 "The structure to fold."
78 )]
79 #[document_returns("The combined monoid value.")]
80 #[document_examples]
81 ///
82 /// ```
83 /// use fp_library::{
84 /// brands::VecBrand,
85 /// functions::*,
86 /// };
87 ///
88 /// let v = vec![1, 2, 3];
89 /// let result = par_ref_fold_map::<VecBrand, _, _>(|x: &i32| x.to_string(), &v);
90 /// assert_eq!(result, "123");
91 /// ```
92 pub fn par_ref_fold_map<
93 'a,
94 Brand: ParRefFoldable,
95 A: Send + Sync + 'a,
96 M: Monoid + Send + 'a,
97 >(
98 f: impl Fn(&A) -> M + Send + Sync + 'a,
99 fa: &Brand::Of<'a, A>,
100 ) -> M {
101 Brand::par_ref_fold_map(f, fa)
102 }
103}
104
105pub use inner::*;