Skip to main content

fp_library/dispatch/
foldable.rs

1//! Dispatch for [`Foldable::fold_right`](crate::classes::Foldable::fold_right),
2//! [`fold_left`](crate::classes::Foldable::fold_left),
3//! [`fold_map`](crate::classes::Foldable::fold_map), and their by-reference
4//! counterparts in [`RefFoldable`](crate::classes::RefFoldable).
5//!
6//! ### Examples
7//!
8//! ```
9//! use fp_library::{
10//! 	brands::*,
11//! 	functions::explicit::*,
12//! 	types::*,
13//! };
14//!
15//! // By-value fold_right (Vec)
16//! let result = fold_right::<RcFnBrand, VecBrand, _, _, _, _>(|a, b| a + b, 0, vec![1, 2, 3]);
17//! assert_eq!(result, 6);
18//!
19//! // By-ref fold_right (Lazy, closure receives &A)
20//! let lazy = RcLazy::new(|| 10);
21//! let result =
22//! 	fold_right::<RcFnBrand, LazyBrand<RcLazyConfig>, _, _, _, _>(|a: &i32, b| *a + b, 5, &lazy);
23//! assert_eq!(result, 15);
24//! ```
25
26#[fp_macros::document_module]
27
28pub(crate) mod inner {
29	use {
30		crate::{
31			classes::{
32				Foldable,
33				LiftFn,
34				Monoid,
35				RefFoldable,
36			},
37			dispatch::{
38				Ref,
39				Val,
40			},
41			kinds::*,
42		},
43		fp_macros::*,
44	};
45
46	// -- FoldRightDispatch --
47
48	/// Trait that routes a fold_right operation to the appropriate type class method.
49	///
50	/// `Fn(A, B) -> B` resolves to [`Val`], `Fn(&A, B) -> B` resolves to [`Ref`].
51	/// The `FA` type parameter is inferred from the container argument: owned
52	/// for Val dispatch, borrowed for Ref dispatch.
53	#[document_type_parameters(
54		"The lifetime of the values.",
55		"The brand of the cloneable function to use.",
56		"The brand of the foldable structure.",
57		"The type of the elements.",
58		"The type of the accumulator.",
59		"The container type (owned or borrowed), inferred from the argument.",
60		"Dispatch marker type, inferred automatically."
61	)]
62	#[document_parameters("The closure implementing this dispatch.")]
63	pub trait FoldRightDispatch<'a, FnBrand, Brand: Kind_cdc7cd43dac7585f, A: 'a, B: 'a, FA, Marker>
64	{
65		/// Perform the dispatched fold_right operation.
66		#[document_signature]
67		#[document_parameters("The initial accumulator value.", "The structure to fold.")]
68		#[document_returns("The final accumulator value.")]
69		#[document_examples]
70		///
71		/// ```
72		/// use fp_library::{
73		/// 	brands::*,
74		/// 	functions::explicit::*,
75		/// };
76		/// let result = fold_right::<RcFnBrand, VecBrand, _, _, _, _>(|a, b| a + b, 0, vec![1, 2, 3]);
77		/// assert_eq!(result, 6);
78		/// ```
79		fn dispatch(
80			self,
81			initial: B,
82			fa: FA,
83		) -> B;
84	}
85
86	/// Routes `Fn(A, B) -> B` closures to [`Foldable::fold_right`].
87	#[document_type_parameters(
88		"The lifetime.",
89		"The cloneable function brand.",
90		"The foldable brand.",
91		"The element type.",
92		"The accumulator type.",
93		"The closure type."
94	)]
95	#[document_parameters("The closure.")]
96	impl<'a, FnBrand, Brand, A, B, F>
97		FoldRightDispatch<
98			'a,
99			FnBrand,
100			Brand,
101			A,
102			B,
103			Apply!(<Brand as Kind!( type Of<'a, T: 'a>: 'a; )>::Of<'a, A>),
104			Val,
105		> for F
106	where
107		Brand: Foldable,
108		FnBrand: LiftFn + 'a,
109		A: 'a + Clone,
110		B: 'a,
111		F: Fn(A, B) -> B + 'a,
112	{
113		#[document_signature]
114		#[document_parameters("The initial accumulator value.", "The structure to fold.")]
115		#[document_returns("The final accumulator value.")]
116		#[document_examples]
117		///
118		/// ```
119		/// use fp_library::{
120		/// 	brands::*,
121		/// 	functions::explicit::*,
122		/// };
123		/// let result = fold_right::<RcFnBrand, VecBrand, _, _, _, _>(|a, b| a + b, 0, vec![1, 2, 3]);
124		/// assert_eq!(result, 6);
125		/// ```
126		fn dispatch(
127			self,
128			initial: B,
129			fa: Apply!(<Brand as Kind!( type Of<'a, T: 'a>: 'a; )>::Of<'a, A>),
130		) -> B {
131			Brand::fold_right::<FnBrand, A, B>(self, initial, fa)
132		}
133	}
134
135	/// Routes `Fn(&A, B) -> B` closures to [`RefFoldable::ref_fold_right`].
136	///
137	/// The container must be passed by reference (`&fa`).
138	#[document_type_parameters(
139		"The lifetime.",
140		"The borrow lifetime.",
141		"The cloneable function brand.",
142		"The foldable brand.",
143		"The element type.",
144		"The accumulator type.",
145		"The closure type."
146	)]
147	#[document_parameters("The closure.")]
148	impl<'a, 'b, FnBrand, Brand, A, B, F>
149		FoldRightDispatch<
150			'a,
151			FnBrand,
152			Brand,
153			A,
154			B,
155			&'b Apply!(<Brand as Kind!( type Of<'a, T: 'a>: 'a; )>::Of<'a, A>),
156			Ref,
157		> for F
158	where
159		Brand: RefFoldable,
160		FnBrand: LiftFn + 'a,
161		A: 'a + Clone,
162		B: 'a,
163		F: Fn(&A, B) -> B + 'a,
164	{
165		#[document_signature]
166		#[document_parameters(
167			"The initial accumulator value.",
168			"A reference to the structure to fold."
169		)]
170		#[document_returns("The final accumulator value.")]
171		#[document_examples]
172		///
173		/// ```
174		/// use fp_library::{
175		/// 	brands::*,
176		/// 	functions::explicit::*,
177		/// 	types::*,
178		/// };
179		/// let lazy = RcLazy::new(|| 10);
180		/// let result =
181		/// 	fold_right::<RcFnBrand, LazyBrand<RcLazyConfig>, _, _, _, _>(|a: &i32, b| *a + b, 5, &lazy);
182		/// assert_eq!(result, 15);
183		/// ```
184		fn dispatch(
185			self,
186			initial: B,
187			fa: &'b Apply!(<Brand as Kind!( type Of<'a, T: 'a>: 'a; )>::Of<'a, A>),
188		) -> B {
189			Brand::ref_fold_right::<FnBrand, A, B>(self, initial, fa)
190		}
191	}
192
193	// -- FoldLeftDispatch --
194
195	/// Trait that routes a fold_left operation to the appropriate type class method.
196	///
197	/// `Fn(B, A) -> B` resolves to [`Val`], `Fn(B, &A) -> B` resolves to [`Ref`].
198	/// The `FA` type parameter is inferred from the container argument: owned
199	/// for Val dispatch, borrowed for Ref dispatch.
200	#[document_type_parameters(
201		"The lifetime of the values.",
202		"The brand of the cloneable function to use.",
203		"The brand of the foldable structure.",
204		"The type of the elements.",
205		"The type of the accumulator.",
206		"The container type (owned or borrowed), inferred from the argument.",
207		"Dispatch marker type, inferred automatically."
208	)]
209	#[document_parameters("The closure implementing this dispatch.")]
210	pub trait FoldLeftDispatch<'a, FnBrand, Brand: Kind_cdc7cd43dac7585f, A: 'a, B: 'a, FA, Marker>
211	{
212		/// Perform the dispatched fold_left operation.
213		#[document_signature]
214		#[document_parameters("The initial accumulator value.", "The structure to fold.")]
215		#[document_returns("The final accumulator value.")]
216		#[document_examples]
217		///
218		/// ```
219		/// use fp_library::{
220		/// 	brands::*,
221		/// 	functions::explicit::*,
222		/// };
223		/// let result = fold_left::<RcFnBrand, VecBrand, _, _, _, _>(|b, a| b + a, 0, vec![1, 2, 3]);
224		/// assert_eq!(result, 6);
225		/// ```
226		fn dispatch(
227			self,
228			initial: B,
229			fa: FA,
230		) -> B;
231	}
232
233	/// Routes `Fn(B, A) -> B` closures to [`Foldable::fold_left`].
234	#[document_type_parameters(
235		"The lifetime.",
236		"The cloneable function brand.",
237		"The foldable brand.",
238		"The element type.",
239		"The accumulator type.",
240		"The closure type."
241	)]
242	#[document_parameters("The closure.")]
243	impl<'a, FnBrand, Brand, A, B, F>
244		FoldLeftDispatch<
245			'a,
246			FnBrand,
247			Brand,
248			A,
249			B,
250			Apply!(<Brand as Kind!( type Of<'a, T: 'a>: 'a; )>::Of<'a, A>),
251			Val,
252		> for F
253	where
254		Brand: Foldable,
255		FnBrand: LiftFn + 'a,
256		A: 'a + Clone,
257		B: 'a,
258		F: Fn(B, A) -> B + 'a,
259	{
260		#[document_signature]
261		#[document_parameters("The initial accumulator value.", "The structure to fold.")]
262		#[document_returns("The final accumulator value.")]
263		#[document_examples]
264		///
265		/// ```
266		/// use fp_library::{
267		/// 	brands::*,
268		/// 	functions::explicit::*,
269		/// };
270		/// let result = fold_left::<RcFnBrand, VecBrand, _, _, _, _>(|b, a| b + a, 0, vec![1, 2, 3]);
271		/// assert_eq!(result, 6);
272		/// ```
273		fn dispatch(
274			self,
275			initial: B,
276			fa: Apply!(<Brand as Kind!( type Of<'a, T: 'a>: 'a; )>::Of<'a, A>),
277		) -> B {
278			Brand::fold_left::<FnBrand, A, B>(self, initial, fa)
279		}
280	}
281
282	/// Routes `Fn(B, &A) -> B` closures to [`RefFoldable::ref_fold_left`].
283	///
284	/// The container must be passed by reference (`&fa`).
285	#[document_type_parameters(
286		"The lifetime.",
287		"The borrow lifetime.",
288		"The cloneable function brand.",
289		"The foldable brand.",
290		"The element type.",
291		"The accumulator type.",
292		"The closure type."
293	)]
294	#[document_parameters("The closure.")]
295	impl<'a, 'b, FnBrand, Brand, A, B, F>
296		FoldLeftDispatch<
297			'a,
298			FnBrand,
299			Brand,
300			A,
301			B,
302			&'b Apply!(<Brand as Kind!( type Of<'a, T: 'a>: 'a; )>::Of<'a, A>),
303			Ref,
304		> for F
305	where
306		Brand: RefFoldable,
307		FnBrand: LiftFn + 'a,
308		A: 'a + Clone,
309		B: 'a,
310		F: Fn(B, &A) -> B + 'a,
311	{
312		#[document_signature]
313		#[document_parameters(
314			"The initial accumulator value.",
315			"A reference to the structure to fold."
316		)]
317		#[document_returns("The final accumulator value.")]
318		#[document_examples]
319		///
320		/// ```
321		/// use fp_library::{
322		/// 	brands::*,
323		/// 	functions::explicit::*,
324		/// 	types::*,
325		/// };
326		/// let lazy = RcLazy::new(|| 10);
327		/// let result =
328		/// 	fold_left::<RcFnBrand, LazyBrand<RcLazyConfig>, _, _, _, _>(|b, a: &i32| b + *a, 5, &lazy);
329		/// assert_eq!(result, 15);
330		/// ```
331		fn dispatch(
332			self,
333			initial: B,
334			fa: &'b Apply!(<Brand as Kind!( type Of<'a, T: 'a>: 'a; )>::Of<'a, A>),
335		) -> B {
336			Brand::ref_fold_left::<FnBrand, A, B>(self, initial, fa)
337		}
338	}
339
340	// -- FoldMapDispatch --
341
342	/// Trait that routes a fold_map operation to the appropriate type class method.
343	///
344	/// `Fn(A) -> M` resolves to [`Val`], `Fn(&A) -> M` resolves to [`Ref`].
345	/// The `FA` type parameter is inferred from the container argument: owned
346	/// for Val dispatch, borrowed for Ref dispatch.
347	#[document_type_parameters(
348		"The lifetime of the values.",
349		"The brand of the cloneable function to use.",
350		"The brand of the foldable structure.",
351		"The type of the elements.",
352		"The monoid type.",
353		"The container type (owned or borrowed), inferred from the argument.",
354		"Dispatch marker type, inferred automatically."
355	)]
356	#[document_parameters("The closure implementing this dispatch.")]
357	pub trait FoldMapDispatch<'a, FnBrand, Brand: Kind_cdc7cd43dac7585f, A: 'a, M, FA, Marker> {
358		/// Perform the dispatched fold_map operation.
359		#[document_signature]
360		#[document_parameters("The structure to fold.")]
361		#[document_returns("The combined monoid value.")]
362		#[document_examples]
363		///
364		/// ```
365		/// use fp_library::{
366		/// 	brands::*,
367		/// 	functions::explicit::*,
368		/// };
369		/// let result = fold_map::<RcFnBrand, VecBrand, _, _, _, _>(|a: i32| a.to_string(), vec![1, 2, 3]);
370		/// assert_eq!(result, "123");
371		/// ```
372		fn dispatch(
373			self,
374			fa: FA,
375		) -> M;
376	}
377
378	/// Routes `Fn(A) -> M` closures to [`Foldable::fold_map`].
379	#[document_type_parameters(
380		"The lifetime.",
381		"The cloneable function brand.",
382		"The foldable brand.",
383		"The element type.",
384		"The monoid type.",
385		"The closure type."
386	)]
387	#[document_parameters("The closure.")]
388	impl<'a, FnBrand, Brand, A, M, F>
389		FoldMapDispatch<
390			'a,
391			FnBrand,
392			Brand,
393			A,
394			M,
395			Apply!(<Brand as Kind!( type Of<'a, T: 'a>: 'a; )>::Of<'a, A>),
396			Val,
397		> for F
398	where
399		Brand: Foldable,
400		FnBrand: LiftFn + 'a,
401		A: 'a + Clone,
402		M: Monoid + 'a,
403		F: Fn(A) -> M + 'a,
404	{
405		#[document_signature]
406		#[document_parameters("The structure to fold.")]
407		#[document_returns("The combined monoid value.")]
408		#[document_examples]
409		///
410		/// ```
411		/// use fp_library::{
412		/// 	brands::*,
413		/// 	functions::explicit::*,
414		/// };
415		/// let result = fold_map::<RcFnBrand, VecBrand, _, _, _, _>(|a: i32| a.to_string(), vec![1, 2, 3]);
416		/// assert_eq!(result, "123");
417		/// ```
418		fn dispatch(
419			self,
420			fa: Apply!(<Brand as Kind!( type Of<'a, T: 'a>: 'a; )>::Of<'a, A>),
421		) -> M {
422			Brand::fold_map::<FnBrand, A, M>(self, fa)
423		}
424	}
425
426	/// Routes `Fn(&A) -> M` closures to [`RefFoldable::ref_fold_map`].
427	///
428	/// The container must be passed by reference (`&fa`).
429	#[document_type_parameters(
430		"The lifetime.",
431		"The borrow lifetime.",
432		"The cloneable function brand.",
433		"The foldable brand.",
434		"The element type.",
435		"The monoid type.",
436		"The closure type."
437	)]
438	#[document_parameters("The closure.")]
439	impl<'a, 'b, FnBrand, Brand, A, M, F>
440		FoldMapDispatch<
441			'a,
442			FnBrand,
443			Brand,
444			A,
445			M,
446			&'b Apply!(<Brand as Kind!( type Of<'a, T: 'a>: 'a; )>::Of<'a, A>),
447			Ref,
448		> for F
449	where
450		Brand: RefFoldable,
451		FnBrand: LiftFn + 'a,
452		A: Clone + 'a,
453		M: Monoid + 'a,
454		F: Fn(&A) -> M + 'a,
455	{
456		#[document_signature]
457		#[document_parameters("A reference to the structure to fold.")]
458		#[document_returns("The combined monoid value.")]
459		#[document_examples]
460		///
461		/// ```
462		/// use fp_library::{
463		/// 	brands::*,
464		/// 	functions::explicit::*,
465		/// 	types::*,
466		/// };
467		/// let lazy = RcLazy::new(|| 10);
468		/// let result =
469		/// 	fold_map::<RcFnBrand, LazyBrand<RcLazyConfig>, _, _, _, _>(|a: &i32| a.to_string(), &lazy);
470		/// assert_eq!(result, "10");
471		/// ```
472		fn dispatch(
473			self,
474			fa: &'b Apply!(<Brand as Kind!( type Of<'a, T: 'a>: 'a; )>::Of<'a, A>),
475		) -> M {
476			Brand::ref_fold_map::<FnBrand, A, M>(self, fa)
477		}
478	}
479
480	// -- Inference wrappers --
481
482	/// Folds a structure from the right, inferring the brand from the container type.
483	///
484	/// The `Brand` type parameter is inferred from the concrete type of `fa`
485	/// via [`InferableBrand`](crate::kinds::InferableBrand_cdc7cd43dac7585f). `FnBrand` must still be specified explicitly.
486	/// Both owned and borrowed containers are supported.
487	///
488	/// For types with multiple brands, use
489	/// [`explicit::fold_right`](crate::functions::explicit::fold_right) with a turbofish.
490	#[document_signature]
491	///
492	#[document_type_parameters(
493		"The lifetime of the values.",
494		"The brand of the cloneable function to use (must be specified explicitly).",
495		"The container type (owned or borrowed). Brand is inferred from this.",
496		"The type of the elements.",
497		"The type of the accumulator.",
498		"Dispatch marker type, inferred automatically."
499	)]
500	///
501	#[document_parameters(
502		"The folding function.",
503		"The initial accumulator value.",
504		"The structure to fold (owned for Val, borrowed for Ref)."
505	)]
506	///
507	#[document_returns("The final accumulator value.")]
508	#[document_examples]
509	///
510	/// ```
511	/// use fp_library::{
512	/// 	brands::*,
513	/// 	functions::*,
514	/// };
515	///
516	/// let result = fold_right::<RcFnBrand, _, _, _, _>(|a, b| a + b, 0, vec![1, 2, 3]);
517	/// assert_eq!(result, 6);
518	/// ```
519	pub fn fold_right<'a, FnBrand, FA, A: 'a + Clone, B: 'a, Marker>(
520		func: impl FoldRightDispatch<
521			'a,
522			FnBrand,
523			<FA as InferableBrand_cdc7cd43dac7585f>::Brand,
524			A,
525			B,
526			FA,
527			Marker,
528		>,
529		initial: B,
530		fa: FA,
531	) -> B
532	where
533		FA: InferableBrand_cdc7cd43dac7585f, {
534		func.dispatch(initial, fa)
535	}
536
537	/// Folds a structure from the left, inferring the brand from the container type.
538	///
539	/// The `Brand` type parameter is inferred from the concrete type of `fa`
540	/// via [`InferableBrand`](crate::kinds::InferableBrand_cdc7cd43dac7585f). `FnBrand` must still be specified explicitly.
541	/// Both owned and borrowed containers are supported.
542	///
543	/// For types with multiple brands, use
544	/// [`explicit::fold_left`](crate::functions::explicit::fold_left) with a turbofish.
545	#[document_signature]
546	///
547	#[document_type_parameters(
548		"The lifetime of the values.",
549		"The brand of the cloneable function to use (must be specified explicitly).",
550		"The container type (owned or borrowed). Brand is inferred from this.",
551		"The type of the elements.",
552		"The type of the accumulator.",
553		"Dispatch marker type, inferred automatically."
554	)]
555	///
556	#[document_parameters(
557		"The folding function.",
558		"The initial accumulator value.",
559		"The structure to fold (owned for Val, borrowed for Ref)."
560	)]
561	///
562	#[document_returns("The final accumulator value.")]
563	#[document_examples]
564	///
565	/// ```
566	/// use fp_library::{
567	/// 	brands::*,
568	/// 	functions::*,
569	/// };
570	///
571	/// let result = fold_left::<RcFnBrand, _, _, _, _>(|b, a| b + a, 0, vec![1, 2, 3]);
572	/// assert_eq!(result, 6);
573	/// ```
574	pub fn fold_left<'a, FnBrand, FA, A: 'a + Clone, B: 'a, Marker>(
575		func: impl FoldLeftDispatch<
576			'a,
577			FnBrand,
578			<FA as InferableBrand_cdc7cd43dac7585f>::Brand,
579			A,
580			B,
581			FA,
582			Marker,
583		>,
584		initial: B,
585		fa: FA,
586	) -> B
587	where
588		FA: InferableBrand_cdc7cd43dac7585f, {
589		func.dispatch(initial, fa)
590	}
591
592	/// Maps values to a monoid and combines them, inferring the brand from the container type.
593	///
594	/// The `Brand` type parameter is inferred from the concrete type of `fa`
595	/// via [`InferableBrand`](crate::kinds::InferableBrand_cdc7cd43dac7585f). `FnBrand` must still be specified explicitly.
596	/// Both owned and borrowed containers are supported.
597	///
598	/// For types with multiple brands, use
599	/// [`explicit::fold_map`](crate::functions::explicit::fold_map) with a turbofish.
600	#[document_signature]
601	///
602	#[document_type_parameters(
603		"The lifetime of the values.",
604		"The brand of the cloneable function to use (must be specified explicitly).",
605		"The container type (owned or borrowed). Brand is inferred from this.",
606		"The type of the elements.",
607		"The monoid type.",
608		"Dispatch marker type, inferred automatically."
609	)]
610	///
611	#[document_parameters(
612		"The mapping function.",
613		"The structure to fold (owned for Val, borrowed for Ref)."
614	)]
615	///
616	#[document_returns("The combined monoid value.")]
617	#[document_examples]
618	///
619	/// ```
620	/// use fp_library::{
621	/// 	brands::*,
622	/// 	functions::*,
623	/// };
624	///
625	/// let result = fold_map::<RcFnBrand, _, _, _, _>(|a: i32| a.to_string(), vec![1, 2, 3]);
626	/// assert_eq!(result, "123");
627	/// ```
628	pub fn fold_map<'a, FnBrand, FA, A: 'a, M: Monoid + 'a, Marker>(
629		func: impl FoldMapDispatch<
630			'a,
631			FnBrand,
632			<FA as InferableBrand_cdc7cd43dac7585f>::Brand,
633			A,
634			M,
635			FA,
636			Marker,
637		>,
638		fa: FA,
639	) -> M
640	where
641		FA: InferableBrand_cdc7cd43dac7585f, {
642		func.dispatch(fa)
643	}
644
645	// -- Explicit dispatch free functions --
646
647	/// Explicit dispatch functions requiring a Brand turbofish.
648	///
649	/// For most use cases, prefer the inference-enabled wrappers from
650	/// [`functions`](crate::functions).
651	pub mod explicit {
652		use super::*;
653
654		/// Folds a structure from the right.
655		///
656		/// Dispatches to [`Foldable::fold_right`] or [`RefFoldable::ref_fold_right`]
657		/// based on whether the closure takes `A` or `&A`.
658		///
659		/// The `Marker` and `FA` type parameters are inferred automatically by the
660		/// compiler from the closure's argument type and the container argument.
661		#[document_signature]
662		#[document_type_parameters(
663			"The lifetime of the values.",
664			"The brand of the cloneable function to use.",
665			"The brand of the foldable structure.",
666			"The type of the elements.",
667			"The type of the accumulator.",
668			"The container type (owned or borrowed), inferred from the argument.",
669			"Dispatch marker type, inferred automatically."
670		)]
671		#[document_parameters(
672			"The folding function.",
673			"The initial accumulator value.",
674			"The structure to fold (owned for Val, borrowed for Ref)."
675		)]
676		#[document_returns("The final accumulator value.")]
677		#[document_examples]
678		///
679		/// ```
680		/// use fp_library::{
681		/// 	brands::*,
682		/// 	functions::explicit::*,
683		/// 	types::*,
684		/// };
685		///
686		/// // By-value
687		/// let result = fold_right::<RcFnBrand, VecBrand, _, _, _, _>(|a, b| a + b, 0, vec![1, 2, 3]);
688		/// assert_eq!(result, 6);
689		///
690		/// // By-ref
691		/// let lazy = RcLazy::new(|| 10);
692		/// let result =
693		/// 	fold_right::<RcFnBrand, LazyBrand<RcLazyConfig>, _, _, _, _>(|a: &i32, b| *a + b, 5, &lazy);
694		/// assert_eq!(result, 15);
695		/// ```
696		pub fn fold_right<
697			'a,
698			FnBrand,
699			Brand: Kind_cdc7cd43dac7585f,
700			A: 'a + Clone,
701			B: 'a,
702			FA,
703			Marker,
704		>(
705			func: impl FoldRightDispatch<'a, FnBrand, Brand, A, B, FA, Marker>,
706			initial: B,
707			fa: FA,
708		) -> B {
709			func.dispatch(initial, fa)
710		}
711
712		/// Folds a structure from the left.
713		///
714		/// Dispatches to [`Foldable::fold_left`] or [`RefFoldable::ref_fold_left`]
715		/// based on whether the closure takes `A` or `&A`.
716		///
717		/// The `Marker` and `FA` type parameters are inferred automatically by the
718		/// compiler from the closure's argument type and the container argument.
719		#[document_signature]
720		#[document_type_parameters(
721			"The lifetime of the values.",
722			"The brand of the cloneable function to use.",
723			"The brand of the foldable structure.",
724			"The type of the elements.",
725			"The type of the accumulator.",
726			"The container type (owned or borrowed), inferred from the argument.",
727			"Dispatch marker type, inferred automatically."
728		)]
729		#[document_parameters(
730			"The folding function.",
731			"The initial accumulator value.",
732			"The structure to fold (owned for Val, borrowed for Ref)."
733		)]
734		#[document_returns("The final accumulator value.")]
735		#[document_examples]
736		///
737		/// ```
738		/// use fp_library::{
739		/// 	brands::*,
740		/// 	functions::explicit::*,
741		/// 	types::*,
742		/// };
743		///
744		/// // By-value
745		/// let result = fold_left::<RcFnBrand, VecBrand, _, _, _, _>(|b, a| b + a, 0, vec![1, 2, 3]);
746		/// assert_eq!(result, 6);
747		///
748		/// // By-ref
749		/// let lazy = RcLazy::new(|| 10);
750		/// let result =
751		/// 	fold_left::<RcFnBrand, LazyBrand<RcLazyConfig>, _, _, _, _>(|b, a: &i32| b + *a, 5, &lazy);
752		/// assert_eq!(result, 15);
753		/// ```
754		pub fn fold_left<
755			'a,
756			FnBrand,
757			Brand: Kind_cdc7cd43dac7585f,
758			A: 'a + Clone,
759			B: 'a,
760			FA,
761			Marker,
762		>(
763			func: impl FoldLeftDispatch<'a, FnBrand, Brand, A, B, FA, Marker>,
764			initial: B,
765			fa: FA,
766		) -> B {
767			func.dispatch(initial, fa)
768		}
769
770		/// Maps values to a monoid and combines them.
771		///
772		/// Dispatches to [`Foldable::fold_map`] or [`RefFoldable::ref_fold_map`]
773		/// based on whether the closure takes `A` or `&A`.
774		///
775		/// The `Marker` and `FA` type parameters are inferred automatically by the
776		/// compiler from the closure's argument type and the container argument.
777		#[document_signature]
778		#[document_type_parameters(
779			"The lifetime of the values.",
780			"The brand of the cloneable function to use.",
781			"The brand of the foldable structure.",
782			"The type of the elements.",
783			"The monoid type.",
784			"The container type (owned or borrowed), inferred from the argument.",
785			"Dispatch marker type, inferred automatically."
786		)]
787		#[document_parameters(
788			"The mapping function.",
789			"The structure to fold (owned for Val, borrowed for Ref)."
790		)]
791		#[document_returns("The combined monoid value.")]
792		#[document_examples]
793		///
794		/// ```
795		/// use fp_library::{
796		/// 	brands::*,
797		/// 	functions::explicit::*,
798		/// 	types::*,
799		/// };
800		///
801		/// // By-value
802		/// let result = fold_map::<RcFnBrand, VecBrand, _, _, _, _>(|a: i32| a.to_string(), vec![1, 2, 3]);
803		/// assert_eq!(result, "123");
804		///
805		/// // By-ref
806		/// let lazy = RcLazy::new(|| 10);
807		/// let result =
808		/// 	fold_map::<RcFnBrand, LazyBrand<RcLazyConfig>, _, _, _, _>(|a: &i32| a.to_string(), &lazy);
809		/// assert_eq!(result, "10");
810		/// ```
811		pub fn fold_map<
812			'a,
813			FnBrand,
814			Brand: Kind_cdc7cd43dac7585f,
815			A: 'a,
816			M: Monoid + 'a,
817			FA,
818			Marker,
819		>(
820			func: impl FoldMapDispatch<'a, FnBrand, Brand, A, M, FA, Marker>,
821			fa: FA,
822		) -> M {
823			func.dispatch(fa)
824		}
825	}
826}
827
828pub use inner::*;