Skip to main content

fp_library/dispatch/
foldable_with_index.rs

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