Skip to main content

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::*;