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 the `InferableBrand` trait. `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		"The brand, inferred via InferableBrand from FA and the element type."
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, Brand>(
520		func: impl FoldRightDispatch<
521			'a,
522			FnBrand,
523			Brand,
524			A,
525			B,
526			FA,
527			<FA as InferableBrand_cdc7cd43dac7585f<'a, Brand, A>>::Marker,
528		>,
529		initial: B,
530		fa: FA,
531	) -> B
532	where
533		Brand: Kind_cdc7cd43dac7585f,
534		FA: InferableBrand_cdc7cd43dac7585f<'a, Brand, A>, {
535		func.dispatch(initial, fa)
536	}
537
538	/// Folds a structure from the left, inferring the brand from the container type.
539	///
540	/// The `Brand` type parameter is inferred from the concrete type of `fa`
541	/// via the `InferableBrand` trait. `FnBrand` must still be specified explicitly.
542	/// Both owned and borrowed containers are supported.
543	///
544	/// For types with multiple brands, use
545	/// [`explicit::fold_left`](crate::functions::explicit::fold_left) with a turbofish.
546	#[document_signature]
547	///
548	#[document_type_parameters(
549		"The lifetime of the values.",
550		"The brand of the cloneable function to use (must be specified explicitly).",
551		"The container type (owned or borrowed). Brand is inferred from this.",
552		"The type of the elements.",
553		"The type of the accumulator.",
554		"The brand, inferred via InferableBrand from FA and the element type."
555	)]
556	///
557	#[document_parameters(
558		"The folding function.",
559		"The initial accumulator value.",
560		"The structure to fold (owned for Val, borrowed for Ref)."
561	)]
562	///
563	#[document_returns("The final accumulator value.")]
564	#[document_examples]
565	///
566	/// ```
567	/// use fp_library::{
568	/// 	brands::*,
569	/// 	functions::*,
570	/// };
571	///
572	/// let result = fold_left::<RcFnBrand, _, _, _, _>(|b, a| b + a, 0, vec![1, 2, 3]);
573	/// assert_eq!(result, 6);
574	/// ```
575	pub fn fold_left<'a, FnBrand, FA, A: 'a + Clone, B: 'a, Brand>(
576		func: impl FoldLeftDispatch<
577			'a,
578			FnBrand,
579			Brand,
580			A,
581			B,
582			FA,
583			<FA as InferableBrand_cdc7cd43dac7585f<'a, Brand, A>>::Marker,
584		>,
585		initial: B,
586		fa: FA,
587	) -> B
588	where
589		Brand: Kind_cdc7cd43dac7585f,
590		FA: InferableBrand_cdc7cd43dac7585f<'a, Brand, A>, {
591		func.dispatch(initial, fa)
592	}
593
594	/// Maps values to a monoid and combines them, inferring the brand from the container type.
595	///
596	/// The `Brand` type parameter is inferred from the concrete type of `fa`
597	/// via the `InferableBrand` trait. `FnBrand` must still be specified explicitly.
598	/// Both owned and borrowed containers are supported.
599	///
600	/// For types with multiple brands, use
601	/// [`explicit::fold_map`](crate::functions::explicit::fold_map) with a turbofish.
602	#[document_signature]
603	///
604	#[document_type_parameters(
605		"The lifetime of the values.",
606		"The brand of the cloneable function to use (must be specified explicitly).",
607		"The container type (owned or borrowed). Brand is inferred from this.",
608		"The type of the elements.",
609		"The monoid type.",
610		"The brand, inferred via InferableBrand from FA and the element type."
611	)]
612	///
613	#[document_parameters(
614		"The mapping function.",
615		"The structure to fold (owned for Val, borrowed for Ref)."
616	)]
617	///
618	#[document_returns("The combined monoid value.")]
619	#[document_examples]
620	///
621	/// ```
622	/// use fp_library::{
623	/// 	brands::*,
624	/// 	functions::*,
625	/// };
626	///
627	/// let result = fold_map::<RcFnBrand, _, _, _, _>(|a: i32| a.to_string(), vec![1, 2, 3]);
628	/// assert_eq!(result, "123");
629	/// ```
630	pub fn fold_map<'a, FnBrand, FA, A: 'a, M: Monoid + 'a, Brand>(
631		func: impl FoldMapDispatch<
632			'a,
633			FnBrand,
634			Brand,
635			A,
636			M,
637			FA,
638			<FA as InferableBrand_cdc7cd43dac7585f<'a, Brand, A>>::Marker,
639		>,
640		fa: FA,
641	) -> M
642	where
643		Brand: Kind_cdc7cd43dac7585f,
644		FA: InferableBrand_cdc7cd43dac7585f<'a, Brand, A>, {
645		func.dispatch(fa)
646	}
647
648	// -- Explicit dispatch free functions --
649
650	/// Explicit dispatch functions requiring a Brand turbofish.
651	///
652	/// For most use cases, prefer the inference-enabled wrappers from
653	/// [`functions`](crate::functions).
654	pub mod explicit {
655		use super::*;
656
657		/// Folds a structure from the right.
658		///
659		/// Dispatches to [`Foldable::fold_right`] or [`RefFoldable::ref_fold_right`]
660		/// based on whether the closure takes `A` or `&A`.
661		///
662		/// The `Marker` and `FA` type parameters are inferred automatically by the
663		/// compiler from the closure's argument type and the container argument.
664		#[document_signature]
665		#[document_type_parameters(
666			"The lifetime of the values.",
667			"The brand of the cloneable function to use.",
668			"The brand of the foldable structure.",
669			"The type of the elements.",
670			"The type of the accumulator.",
671			"The container type (owned or borrowed), inferred from the argument.",
672			"Dispatch marker type, inferred automatically."
673		)]
674		#[document_parameters(
675			"The folding function.",
676			"The initial accumulator value.",
677			"The structure to fold (owned for Val, borrowed for Ref)."
678		)]
679		#[document_returns("The final accumulator value.")]
680		#[document_examples]
681		///
682		/// ```
683		/// use fp_library::{
684		/// 	brands::*,
685		/// 	functions::explicit::*,
686		/// 	types::*,
687		/// };
688		///
689		/// // By-value
690		/// let result = fold_right::<RcFnBrand, VecBrand, _, _, _, _>(|a, b| a + b, 0, vec![1, 2, 3]);
691		/// assert_eq!(result, 6);
692		///
693		/// // By-ref
694		/// let lazy = RcLazy::new(|| 10);
695		/// let result =
696		/// 	fold_right::<RcFnBrand, LazyBrand<RcLazyConfig>, _, _, _, _>(|a: &i32, b| *a + b, 5, &lazy);
697		/// assert_eq!(result, 15);
698		/// ```
699		pub fn fold_right<
700			'a,
701			FnBrand,
702			Brand: Kind_cdc7cd43dac7585f,
703			A: 'a + Clone,
704			B: 'a,
705			FA,
706			Marker,
707		>(
708			func: impl FoldRightDispatch<'a, FnBrand, Brand, A, B, FA, Marker>,
709			initial: B,
710			fa: FA,
711		) -> B {
712			func.dispatch(initial, fa)
713		}
714
715		/// Folds a structure from the left.
716		///
717		/// Dispatches to [`Foldable::fold_left`] or [`RefFoldable::ref_fold_left`]
718		/// based on whether the closure takes `A` or `&A`.
719		///
720		/// The `Marker` and `FA` type parameters are inferred automatically by the
721		/// compiler from the closure's argument type and the container argument.
722		#[document_signature]
723		#[document_type_parameters(
724			"The lifetime of the values.",
725			"The brand of the cloneable function to use.",
726			"The brand of the foldable structure.",
727			"The type of the elements.",
728			"The type of the accumulator.",
729			"The container type (owned or borrowed), inferred from the argument.",
730			"Dispatch marker type, inferred automatically."
731		)]
732		#[document_parameters(
733			"The folding function.",
734			"The initial accumulator value.",
735			"The structure to fold (owned for Val, borrowed for Ref)."
736		)]
737		#[document_returns("The final accumulator value.")]
738		#[document_examples]
739		///
740		/// ```
741		/// use fp_library::{
742		/// 	brands::*,
743		/// 	functions::explicit::*,
744		/// 	types::*,
745		/// };
746		///
747		/// // By-value
748		/// let result = fold_left::<RcFnBrand, VecBrand, _, _, _, _>(|b, a| b + a, 0, vec![1, 2, 3]);
749		/// assert_eq!(result, 6);
750		///
751		/// // By-ref
752		/// let lazy = RcLazy::new(|| 10);
753		/// let result =
754		/// 	fold_left::<RcFnBrand, LazyBrand<RcLazyConfig>, _, _, _, _>(|b, a: &i32| b + *a, 5, &lazy);
755		/// assert_eq!(result, 15);
756		/// ```
757		pub fn fold_left<
758			'a,
759			FnBrand,
760			Brand: Kind_cdc7cd43dac7585f,
761			A: 'a + Clone,
762			B: 'a,
763			FA,
764			Marker,
765		>(
766			func: impl FoldLeftDispatch<'a, FnBrand, Brand, A, B, FA, Marker>,
767			initial: B,
768			fa: FA,
769		) -> B {
770			func.dispatch(initial, fa)
771		}
772
773		/// Maps values to a monoid and combines them.
774		///
775		/// Dispatches to [`Foldable::fold_map`] or [`RefFoldable::ref_fold_map`]
776		/// based on whether the closure takes `A` or `&A`.
777		///
778		/// The `Marker` and `FA` type parameters are inferred automatically by the
779		/// compiler from the closure's argument type and the container argument.
780		#[document_signature]
781		#[document_type_parameters(
782			"The lifetime of the values.",
783			"The brand of the cloneable function to use.",
784			"The brand of the foldable structure.",
785			"The type of the elements.",
786			"The monoid type.",
787			"The container type (owned or borrowed), inferred from the argument.",
788			"Dispatch marker type, inferred automatically."
789		)]
790		#[document_parameters(
791			"The mapping function.",
792			"The structure to fold (owned for Val, borrowed for Ref)."
793		)]
794		#[document_returns("The combined monoid value.")]
795		#[document_examples]
796		///
797		/// ```
798		/// use fp_library::{
799		/// 	brands::*,
800		/// 	functions::explicit::*,
801		/// 	types::*,
802		/// };
803		///
804		/// // By-value
805		/// let result = fold_map::<RcFnBrand, VecBrand, _, _, _, _>(|a: i32| a.to_string(), vec![1, 2, 3]);
806		/// assert_eq!(result, "123");
807		///
808		/// // By-ref
809		/// let lazy = RcLazy::new(|| 10);
810		/// let result =
811		/// 	fold_map::<RcFnBrand, LazyBrand<RcLazyConfig>, _, _, _, _>(|a: &i32| a.to_string(), &lazy);
812		/// assert_eq!(result, "10");
813		/// ```
814		pub fn fold_map<
815			'a,
816			FnBrand,
817			Brand: Kind_cdc7cd43dac7585f,
818			A: 'a,
819			M: Monoid + 'a,
820			FA,
821			Marker,
822		>(
823			func: impl FoldMapDispatch<'a, FnBrand, Brand, A, M, FA, Marker>,
824			fa: FA,
825		) -> M {
826			func.dispatch(fa)
827		}
828	}
829}
830
831pub use inner::*;