Skip to main content

fp_library/types/
pair.rs

1//! Two-value container with [`Bifunctor`](crate::classes::Bifunctor) and dual [`Functor`](crate::classes::Functor) instances.
2//!
3//! Can be used as a bifunctor over both values [`PairBrand`](crate::brands::PairBrand), or as a functor/monad by fixing either the first value [`PairFirstAppliedBrand`](crate::brands::PairFirstAppliedBrand) or second value [`PairSecondAppliedBrand`](crate::brands::PairSecondAppliedBrand).
4
5#[fp_macros::document_module]
6mod inner {
7	use {
8		crate::{
9			Apply,
10			brands::{
11				PairBrand,
12				PairFirstAppliedBrand,
13				PairSecondAppliedBrand,
14			},
15			classes::*,
16			dispatch::Ref,
17			impl_kind,
18			kinds::*,
19		},
20		core::ops::ControlFlow,
21		fp_macros::*,
22	};
23
24	/// Wraps two values.
25	///
26	/// A simple tuple struct that holds two values of potentially different types.
27	///
28	/// ### Higher-Kinded Type Representation
29	///
30	/// This type has multiple higher-kinded representations:
31	/// - [`PairBrand`](crate::brands::PairBrand): fully polymorphic over both values (bifunctor).
32	/// - [`PairFirstAppliedBrand<First>`](crate::brands::PairFirstAppliedBrand): the first value type is fixed, polymorphic over the second (functor over second).
33	/// - [`PairSecondAppliedBrand<Second>`](crate::brands::PairSecondAppliedBrand): the second value type is fixed, polymorphic over the first (functor over first).
34	///
35	/// ### Serialization
36	///
37	/// This type supports serialization and deserialization via [`serde`](https://serde.rs) when the `serde` feature is enabled.
38	#[document_type_parameters("The type of the first value.", "The type of the second value.")]
39	///
40	#[cfg_attr(feature = "serde", derive(serde::Serialize, serde::Deserialize))]
41	#[derive(Clone, Copy, Debug, Default, Eq, Hash, Ord, PartialEq, PartialOrd)]
42	pub struct Pair<First, Second>(
43		/// The first value.
44		pub First,
45		/// The second value.
46		pub Second,
47	);
48
49	impl_kind! {
50		for PairBrand {
51			type Of<First,Second> = Pair<First, Second>;
52		}
53	}
54
55	impl_kind! {
56		for PairBrand {
57			type Of<'a, First: 'a, Second: 'a>: 'a = Pair<First, Second>;
58		}
59	}
60
61	#[document_type_parameters("The type of the first value.", "The type of the second value.")]
62	#[document_parameters("The pair instance.")]
63	impl<First, Second> Pair<First, Second> {
64		/// Maps functions over both values in the pair.
65		///
66		/// See [`Bifunctor::bimap`] for the type class version.
67		#[document_signature]
68		///
69		#[document_type_parameters(
70			"The type of the mapped first value.",
71			"The type of the mapped second value."
72		)]
73		///
74		#[document_parameters(
75			"The function to apply to the first value.",
76			"The function to apply to the second value."
77		)]
78		///
79		#[document_returns("A new pair containing the mapped values.")]
80		///
81		#[document_examples]
82		///
83		/// ```
84		/// use fp_library::types::*;
85		///
86		/// let x = Pair(1, 5);
87		/// assert_eq!(x.bimap(|a| a + 1, |b| b * 2), Pair(2, 10));
88		/// ```
89		pub fn bimap<B, D>(
90			self,
91			f: impl FnOnce(First) -> B,
92			g: impl FnOnce(Second) -> D,
93		) -> Pair<B, D> {
94			Pair(f(self.0), g(self.1))
95		}
96
97		/// Maps a function over the first value in the pair.
98		///
99		/// See [`Bifunctor::bimap`] for the type class version.
100		#[document_signature]
101		///
102		#[document_type_parameters("The type of the mapped first value.")]
103		///
104		#[document_parameters("The function to apply to the first value.")]
105		///
106		#[document_returns("A new pair with the transformed first value.")]
107		///
108		#[document_examples]
109		///
110		/// ```
111		/// use fp_library::types::*;
112		///
113		/// let x = Pair(1, 5);
114		/// assert_eq!(x.map_first(|a| a + 1), Pair(2, 5));
115		/// ```
116		pub fn map_first<B>(
117			self,
118			f: impl FnOnce(First) -> B,
119		) -> Pair<B, Second> {
120			Pair(f(self.0), self.1)
121		}
122
123		/// Maps a function over the second value in the pair.
124		///
125		/// See [`Bifunctor::bimap`] for the type class version.
126		#[document_signature]
127		///
128		#[document_type_parameters("The type of the mapped second value.")]
129		///
130		#[document_parameters("The function to apply to the second value.")]
131		///
132		#[document_returns("A new pair with the transformed second value.")]
133		///
134		#[document_examples]
135		///
136		/// ```
137		/// use fp_library::types::*;
138		///
139		/// let x = Pair(1, 5);
140		/// assert_eq!(x.map_second(|b| b * 2), Pair(1, 10));
141		/// ```
142		pub fn map_second<D>(
143			self,
144			g: impl FnOnce(Second) -> D,
145		) -> Pair<First, D> {
146			Pair(self.0, g(self.1))
147		}
148
149		/// Folds both values into a single result.
150		///
151		/// Applies two functions to the first and second values respectively,
152		/// then combines the results using `FnOnce`.
153		#[document_signature]
154		///
155		#[document_type_parameters("The result type.")]
156		///
157		#[document_parameters(
158			"The function to apply to the first value.",
159			"The function to apply to the second value.",
160			"The function to combine the results."
161		)]
162		///
163		#[document_returns("The combined result.")]
164		///
165		#[document_examples]
166		///
167		/// ```
168		/// use fp_library::types::*;
169		///
170		/// let x = Pair(1, 2);
171		/// let y = x.fold(|a| a.to_string(), |b| b.to_string(), |a, b| format!("{a},{b}"));
172		/// assert_eq!(y, "1,2");
173		/// ```
174		pub fn fold<C>(
175			self,
176			f: impl FnOnce(First) -> C,
177			g: impl FnOnce(Second) -> C,
178			combine: impl FnOnce(C, C) -> C,
179		) -> C {
180			combine(f(self.0), g(self.1))
181		}
182
183		/// Folds the pair from right to left using two step functions.
184		///
185		/// See [`Bifoldable::bi_fold_right`] for the type class version.
186		#[document_signature]
187		///
188		#[document_type_parameters("The accumulator type.")]
189		///
190		#[document_parameters(
191			"The step function for the first value.",
192			"The step function for the second value.",
193			"The initial accumulator."
194		)]
195		///
196		#[document_returns("The result of folding: `f(first, g(second, z))`.")]
197		///
198		#[document_examples]
199		///
200		/// ```
201		/// use fp_library::types::*;
202		///
203		/// let x = Pair(3, 5);
204		/// assert_eq!(x.bi_fold_right(|a, acc| acc - a, |b, acc| acc + b, 0), 2);
205		/// ```
206		pub fn bi_fold_right<C>(
207			self,
208			f: impl FnOnce(First, C) -> C,
209			g: impl FnOnce(Second, C) -> C,
210			z: C,
211		) -> C {
212			f(self.0, g(self.1, z))
213		}
214
215		/// Folds the pair from left to right using two step functions.
216		///
217		/// See [`Bifoldable::bi_fold_left`] for the type class version.
218		#[document_signature]
219		///
220		#[document_type_parameters("The accumulator type.")]
221		///
222		#[document_parameters(
223			"The step function for the first value.",
224			"The step function for the second value.",
225			"The initial accumulator."
226		)]
227		///
228		#[document_returns("The result of folding: `g(f(z, first), second)`.")]
229		///
230		#[document_examples]
231		///
232		/// ```
233		/// use fp_library::types::*;
234		///
235		/// let x = Pair(3, 5);
236		/// assert_eq!(x.bi_fold_left(|acc, a| acc - a, |acc, b| acc + b, 0), 2);
237		/// ```
238		pub fn bi_fold_left<C>(
239			self,
240			f: impl FnOnce(C, First) -> C,
241			g: impl FnOnce(C, Second) -> C,
242			z: C,
243		) -> C {
244			g(f(z, self.0), self.1)
245		}
246
247		/// Maps both values to a monoid and combines the results.
248		///
249		/// See [`Bifoldable::bi_fold_map`] for the type class version.
250		#[document_signature]
251		///
252		#[document_type_parameters("The monoid type.")]
253		///
254		#[document_parameters(
255			"The function mapping the first value to the monoid.",
256			"The function mapping the second value to the monoid."
257		)]
258		///
259		#[document_returns("The combined monoid value.")]
260		///
261		#[document_examples]
262		///
263		/// ```
264		/// use fp_library::types::*;
265		///
266		/// let x = Pair(3, 5);
267		/// assert_eq!(x.bi_fold_map(|a: i32| a.to_string(), |b: i32| b.to_string()), "35".to_string());
268		/// ```
269		pub fn bi_fold_map<M: Semigroup>(
270			self,
271			f: impl FnOnce(First) -> M,
272			g: impl FnOnce(Second) -> M,
273		) -> M {
274			Semigroup::append(f(self.0), g(self.1))
275		}
276	}
277
278	#[document_type_parameters(
279		"The lifetime of the values.",
280		"The type of the first value.",
281		"The type of the second value."
282	)]
283	#[document_parameters("The pair instance.")]
284	impl<'a, First: 'a, Second: 'a> Pair<First, Second> {
285		/// Traverses the pair with two effectful functions.
286		///
287		/// See [`Bitraversable::bi_traverse`] for the type class version.
288		#[document_signature]
289		///
290		#[document_type_parameters(
291			"The output type for the first value.",
292			"The output type for the second value.",
293			"The applicative context."
294		)]
295		///
296		#[document_parameters(
297			"The function for the first value.",
298			"The function for the second value."
299		)]
300		///
301		#[document_returns("A pair of the transformed values wrapped in the applicative context.")]
302		///
303		#[document_examples]
304		///
305		/// ```
306		/// use fp_library::{
307		/// 	brands::*,
308		/// 	types::*,
309		/// };
310		///
311		/// let x = Pair(3, 5);
312		/// let y = x.bi_traverse::<_, _, OptionBrand>(|a| Some(a + 1), |b| Some(b * 2));
313		/// assert_eq!(y, Some(Pair(4, 10)));
314		/// ```
315		pub fn bi_traverse<C: 'a + Clone, D: 'a + Clone, F: Applicative>(
316			self,
317			f: impl Fn(First) -> Apply!(<F as Kind!( type Of<'a, T: 'a>: 'a; )>::Of<'a, C>) + 'a,
318			g: impl Fn(Second) -> Apply!(<F as Kind!( type Of<'a, T: 'a>: 'a; )>::Of<'a, D>) + 'a,
319		) -> Apply!(<F as Kind!( type Of<'a, T: 'a>: 'a; )>::Of<'a, Pair<C, D>>)
320		where
321			Pair<C, D>: Clone, {
322			F::lift2(|c, d| Pair(c, d), f(self.0), g(self.1))
323		}
324	}
325
326	#[document_type_parameters("The type of the first value.", "The type of the second value.")]
327	#[document_parameters("The pair instance.")]
328	impl<First: Semigroup, Second> Pair<First, Second> {
329		/// Chains a computation over the second value, combining first values via their semigroup.
330		///
331		/// See [`Semimonad::bind`] for the type class version
332		/// (via [`PairFirstAppliedBrand`]).
333		#[document_signature]
334		///
335		#[document_type_parameters("The type of the new second value.")]
336		///
337		#[document_parameters("The function to apply to the second value.")]
338		///
339		#[document_returns(
340			"A new pair where the first values are combined and the second value is transformed."
341		)]
342		///
343		#[document_examples]
344		///
345		/// ```
346		/// use fp_library::types::*;
347		///
348		/// assert_eq!(
349		/// 	Pair("a".to_string(), 5).bind(|x| Pair("b".to_string(), x * 2)),
350		/// 	Pair("ab".to_string(), 10)
351		/// );
352		/// ```
353		pub fn bind<C>(
354			self,
355			f: impl FnOnce(Second) -> Pair<First, C>,
356		) -> Pair<First, C> {
357			let Pair(first, second) = self;
358			let Pair(next_first, next_second) = f(second);
359			Pair(Semigroup::append(first, next_first), next_second)
360		}
361	}
362
363	#[document_type_parameters("The type of the first value.", "The type of the second value.")]
364	#[document_parameters("The pair instance.")]
365	impl<First, Second: Semigroup> Pair<First, Second> {
366		/// Chains a computation over the first value, combining second values via their semigroup.
367		///
368		/// See [`Semimonad::bind`] for the type class version
369		/// (via [`PairSecondAppliedBrand`]).
370		#[document_signature]
371		///
372		#[document_type_parameters("The type of the new first value.")]
373		///
374		#[document_parameters("The function to apply to the first value.")]
375		///
376		#[document_returns(
377			"A new pair where the first value is transformed and the second values are combined."
378		)]
379		///
380		#[document_examples]
381		///
382		/// ```
383		/// use fp_library::types::*;
384		///
385		/// assert_eq!(
386		/// 	Pair(5, "a".to_string()).bind_first(|x| Pair(x * 2, "b".to_string())),
387		/// 	Pair(10, "ab".to_string())
388		/// );
389		/// ```
390		pub fn bind_first<C>(
391			self,
392			f: impl FnOnce(First) -> Pair<C, Second>,
393		) -> Pair<C, Second> {
394			let Pair(first, second) = self;
395			let Pair(next_first, next_second) = f(first);
396			Pair(next_first, Semigroup::append(second, next_second))
397		}
398	}
399
400	impl Bifunctor for PairBrand {
401		/// Maps functions over the values in the pair.
402		///
403		/// This method applies one function to the first value and another to the second value.
404		#[document_signature]
405		///
406		#[document_type_parameters(
407			"The lifetime of the values.",
408			"The type of the first value.",
409			"The type of the mapped first value.",
410			"The type of the second value.",
411			"The type of the mapped second value."
412		)]
413		///
414		#[document_parameters(
415			"The function to apply to the first value.",
416			"The function to apply to the second value.",
417			"The pair to map over."
418		)]
419		///
420		#[document_returns("A new pair containing the mapped values.")]
421		#[document_examples]
422		///
423		/// ```
424		/// use fp_library::{
425		/// 	brands::*,
426		/// 	functions::*,
427		/// 	types::*,
428		/// };
429		///
430		/// let x = Pair(1, 5);
431		/// assert_eq!(
432		/// 	explicit::bimap::<PairBrand, _, _, _, _, _, _>((|a| a + 1, |b| b * 2), x),
433		/// 	Pair(2, 10)
434		/// );
435		/// ```
436		fn bimap<'a, A: 'a, B: 'a, C: 'a, D: 'a>(
437			f: impl Fn(A) -> B + 'a,
438			g: impl Fn(C) -> D + 'a,
439			p: Apply!(<Self as Kind!( type Of<'a, A: 'a, B: 'a>: 'a; )>::Of<'a, A, C>),
440		) -> Apply!(<Self as Kind!( type Of<'a, A: 'a, B: 'a>: 'a; )>::Of<'a, B, D>) {
441			p.bimap(f, g)
442		}
443	}
444
445	impl RefBifunctor for PairBrand {
446		/// Maps functions over the values in the pair by reference.
447		///
448		/// This method applies one function to a reference of the first value and another
449		/// to a reference of the second value, producing a new pair with mapped values.
450		/// The original pair is borrowed, not consumed.
451		#[document_signature]
452		///
453		#[document_type_parameters(
454			"The lifetime of the values.",
455			"The type of the first value.",
456			"The type of the mapped first value.",
457			"The type of the second value.",
458			"The type of the mapped second value."
459		)]
460		///
461		#[document_parameters(
462			"The function to apply to a reference of the first value.",
463			"The function to apply to a reference of the second value.",
464			"The pair to map over by reference."
465		)]
466		///
467		#[document_returns("A new pair containing the mapped values.")]
468		#[document_examples]
469		///
470		/// ```
471		/// use fp_library::{
472		/// 	brands::*,
473		/// 	classes::ref_bifunctor::*,
474		/// 	types::*,
475		/// };
476		///
477		/// let x = Pair(1, 5);
478		/// assert_eq!(ref_bimap::<PairBrand, _, _, _, _>(|a| *a + 1, |b| *b * 2, &x), Pair(2, 10));
479		/// ```
480		fn ref_bimap<'a, A: 'a, B: 'a, C: 'a, D: 'a>(
481			f: impl Fn(&A) -> B + 'a,
482			g: impl Fn(&C) -> D + 'a,
483			p: &Apply!(<Self as Kind!( type Of<'a, A: 'a, B: 'a>: 'a; )>::Of<'a, A, C>),
484		) -> Apply!(<Self as Kind!( type Of<'a, A: 'a, B: 'a>: 'a; )>::Of<'a, B, D>) {
485			Pair(f(&p.0), g(&p.1))
486		}
487	}
488
489	impl RefBifoldable for PairBrand {
490		/// Folds the pair from right to left by reference using two step functions.
491		///
492		/// Folds `Pair(a, b)` as `f(&a, g(&b, z))` without consuming the pair.
493		#[document_signature]
494		///
495		#[document_type_parameters(
496			"The lifetime of the values.",
497			"The brand of the cloneable function to use.",
498			"The type of the first value.",
499			"The type of the second value.",
500			"The accumulator type."
501		)]
502		///
503		#[document_parameters(
504			"The step function for a reference to the first value.",
505			"The step function for a reference to the second value.",
506			"The initial accumulator.",
507			"The pair to fold by reference."
508		)]
509		///
510		#[document_returns("`f(&a, g(&b, z))`.")]
511		#[document_examples]
512		///
513		/// ```
514		/// use fp_library::{
515		/// 	brands::*,
516		/// 	classes::ref_bifoldable::*,
517		/// 	types::*,
518		/// };
519		///
520		/// let x = Pair(3, 5);
521		/// assert_eq!(
522		/// 	ref_bi_fold_right::<RcFnBrand, PairBrand, _, _, _>(
523		/// 		|a: &i32, acc| acc - *a,
524		/// 		|b: &i32, acc| acc + *b,
525		/// 		0,
526		/// 		&x,
527		/// 	),
528		/// 	2
529		/// );
530		/// ```
531		fn ref_bi_fold_right<'a, FnBrand: LiftFn + 'a, A: 'a + Clone, B: 'a + Clone, C: 'a>(
532			f: impl Fn(&A, C) -> C + 'a,
533			g: impl Fn(&B, C) -> C + 'a,
534			z: C,
535			p: &Apply!(<Self as Kind!( type Of<'a, A: 'a, B: 'a>: 'a; )>::Of<'a, A, B>),
536		) -> C {
537			f(&p.0, g(&p.1, z))
538		}
539	}
540
541	impl RefBitraversable for PairBrand {
542		/// Traverses the pair by reference with two effectful functions.
543		///
544		/// Applies `f` to a reference to the first value and `g` to a reference to the second
545		/// value, combining the effects via `lift2` without consuming the pair.
546		#[document_signature]
547		///
548		#[document_type_parameters(
549			"The lifetime of the values.",
550			"The brand of the cloneable function wrapper.",
551			"The type of the first value.",
552			"The type of the second value.",
553			"The output type for the first value.",
554			"The output type for the second value.",
555			"The applicative context."
556		)]
557		///
558		#[document_parameters(
559			"The function applied to a reference to the first value.",
560			"The function applied to a reference to the second value.",
561			"The pair to traverse by reference."
562		)]
563		///
564		#[document_returns("`lift2(Pair, f(&a), g(&b))`.")]
565		#[document_examples]
566		///
567		/// ```
568		/// use fp_library::{
569		/// 	brands::*,
570		/// 	classes::ref_bitraversable::*,
571		/// 	types::*,
572		/// };
573		///
574		/// let x = Pair(3, 5);
575		/// assert_eq!(
576		/// 	ref_bi_traverse::<PairBrand, RcFnBrand, _, _, _, _, OptionBrand>(
577		/// 		|a: &i32| Some(a + 1),
578		/// 		|b: &i32| Some(b * 2),
579		/// 		&x,
580		/// 	),
581		/// 	Some(Pair(4, 10))
582		/// );
583		/// ```
584		fn ref_bi_traverse<
585			'a,
586			FnBrand,
587			A: 'a + Clone,
588			B: 'a + Clone,
589			C: 'a + Clone,
590			D: 'a + Clone,
591			F: Applicative,
592		>(
593			f: impl Fn(&A) -> Apply!(<F as Kind!( type Of<'a, T: 'a>: 'a; )>::Of<'a, C>) + 'a,
594			g: impl Fn(&B) -> Apply!(<F as Kind!( type Of<'a, T: 'a>: 'a; )>::Of<'a, D>) + 'a,
595			p: &Apply!(<Self as Kind!( type Of<'a, A: 'a, B: 'a>: 'a; )>::Of<'a, A, B>),
596		) -> Apply!(<F as Kind!( type Of<'a, T: 'a>: 'a; )>::Of<'a, Apply!(<Self as Kind!( type Of<'a, A: 'a, B: 'a>: 'a; )>::Of<'a, C, D>)>)
597		where
598			FnBrand: LiftFn + 'a,
599			Apply!(<Self as Kind!( type Of<'a, A: 'a, B: 'a>: 'a; )>::Of<'a, C, D>): Clone,
600			Apply!(<F as Kind!( type Of<'a, T: 'a>: 'a; )>::Of<'a, C>): Clone,
601			Apply!(<F as Kind!( type Of<'a, T: 'a>: 'a; )>::Of<'a, D>): Clone, {
602			F::lift2(|c, d| Pair(c, d), f(&p.0), g(&p.1))
603		}
604	}
605
606	impl Bifoldable for PairBrand {
607		/// Folds the pair from right to left using two step functions.
608		///
609		/// Folds `Pair(a, b)` as `f(a, g(b, z))`.
610		#[document_signature]
611		///
612		#[document_type_parameters(
613			"The lifetime of the values.",
614			"The brand of the cloneable function to use.",
615			"The type of the first value.",
616			"The type of the second value.",
617			"The accumulator type."
618		)]
619		///
620		#[document_parameters(
621			"The step function for the first value.",
622			"The step function for the second value.",
623			"The initial accumulator.",
624			"The pair to fold."
625		)]
626		///
627		#[document_returns("`f(a, g(b, z))`.")]
628		#[document_examples]
629		///
630		/// ```
631		/// use fp_library::{
632		/// 	brands::*,
633		/// 	functions::*,
634		/// 	types::*,
635		/// };
636		///
637		/// let x = Pair(3, 5);
638		/// assert_eq!(
639		/// 	explicit::bi_fold_right::<RcFnBrand, PairBrand, _, _, _, _, _>(
640		/// 		(|a, acc| acc - a, |b, acc| acc + b),
641		/// 		0,
642		/// 		x
643		/// 	),
644		/// 	2
645		/// );
646		/// ```
647		fn bi_fold_right<'a, FnBrand: CloneFn + 'a, A: 'a + Clone, B: 'a + Clone, C: 'a>(
648			f: impl Fn(A, C) -> C + 'a,
649			g: impl Fn(B, C) -> C + 'a,
650			z: C,
651			p: Apply!(<Self as Kind!( type Of<'a, A: 'a, B: 'a>: 'a; )>::Of<'a, A, B>),
652		) -> C {
653			p.bi_fold_right(f, g, z)
654		}
655
656		/// Folds the pair from left to right using two step functions.
657		///
658		/// Folds `Pair(a, b)` as `g(f(z, a), b)`.
659		#[document_signature]
660		///
661		#[document_type_parameters(
662			"The lifetime of the values.",
663			"The brand of the cloneable function to use.",
664			"The type of the first value.",
665			"The type of the second value.",
666			"The accumulator type."
667		)]
668		///
669		#[document_parameters(
670			"The step function for the first value.",
671			"The step function for the second value.",
672			"The initial accumulator.",
673			"The pair to fold."
674		)]
675		///
676		#[document_returns("`g(f(z, a), b)`.")]
677		#[document_examples]
678		///
679		/// ```
680		/// use fp_library::{
681		/// 	brands::*,
682		/// 	functions::*,
683		/// 	types::*,
684		/// };
685		///
686		/// let x = Pair(3, 5);
687		/// assert_eq!(
688		/// 	explicit::bi_fold_left::<RcFnBrand, PairBrand, _, _, _, _, _>(
689		/// 		(|acc, a| acc - a, |acc, b| acc + b),
690		/// 		0,
691		/// 		x
692		/// 	),
693		/// 	2
694		/// );
695		/// ```
696		fn bi_fold_left<'a, FnBrand: CloneFn + 'a, A: 'a + Clone, B: 'a + Clone, C: 'a>(
697			f: impl Fn(C, A) -> C + 'a,
698			g: impl Fn(C, B) -> C + 'a,
699			z: C,
700			p: Apply!(<Self as Kind!( type Of<'a, A: 'a, B: 'a>: 'a; )>::Of<'a, A, B>),
701		) -> C {
702			p.bi_fold_left(f, g, z)
703		}
704
705		/// Maps both values to a monoid and combines the results.
706		///
707		/// Computes `Semigroup::append(f(a), g(b))` for `Pair(a, b)`.
708		#[document_signature]
709		///
710		#[document_type_parameters(
711			"The lifetime of the values.",
712			"The brand of the cloneable function to use.",
713			"The type of the first value.",
714			"The type of the second value.",
715			"The monoid type."
716		)]
717		///
718		#[document_parameters(
719			"The function mapping the first value to the monoid.",
720			"The function mapping the second value to the monoid.",
721			"The pair to fold."
722		)]
723		///
724		#[document_returns("`Semigroup::append(f(a), g(b))`.")]
725		#[document_examples]
726		///
727		/// ```
728		/// use fp_library::{
729		/// 	brands::*,
730		/// 	functions::*,
731		/// 	types::*,
732		/// };
733		///
734		/// assert_eq!(
735		/// 	explicit::bi_fold_map::<RcFnBrand, PairBrand, _, _, _, _, _>(
736		/// 		(|a: i32| a.to_string(), |b: i32| b.to_string()),
737		/// 		Pair(3, 5),
738		/// 	),
739		/// 	"35".to_string()
740		/// );
741		/// ```
742		fn bi_fold_map<'a, FnBrand: CloneFn + 'a, A: 'a + Clone, B: 'a + Clone, M>(
743			f: impl Fn(A) -> M + 'a,
744			g: impl Fn(B) -> M + 'a,
745			p: Apply!(<Self as Kind!( type Of<'a, A: 'a, B: 'a>: 'a; )>::Of<'a, A, B>),
746		) -> M
747		where
748			M: Monoid + 'a, {
749			p.bi_fold_map(f, g)
750		}
751	}
752
753	impl Bitraversable for PairBrand {
754		/// Traverses the pair with two effectful functions.
755		///
756		/// Applies `f` to the first value and `g` to the second value,
757		/// combining the effects via `lift2`.
758		#[document_signature]
759		///
760		#[document_type_parameters(
761			"The lifetime of the values.",
762			"The type of the first value.",
763			"The type of the second value.",
764			"The output type for the first value.",
765			"The output type for the second value.",
766			"The applicative context."
767		)]
768		///
769		#[document_parameters(
770			"The function applied to the first value.",
771			"The function applied to the second value.",
772			"The pair to traverse."
773		)]
774		///
775		#[document_returns("`lift2(Pair, f(a), g(b))`.")]
776		#[document_examples]
777		///
778		/// ```
779		/// use fp_library::{
780		/// 	brands::*,
781		/// 	functions::*,
782		/// 	types::*,
783		/// };
784		///
785		/// let x = Pair(3, 5);
786		/// assert_eq!(
787		/// 	explicit::bi_traverse::<RcFnBrand, PairBrand, _, _, _, _, OptionBrand, _, _>(
788		/// 		(|a: i32| Some(a + 1), |b: i32| Some(b * 2)),
789		/// 		x,
790		/// 	),
791		/// 	Some(Pair(4, 10))
792		/// );
793		/// ```
794		fn bi_traverse<
795			'a,
796			A: 'a + Clone,
797			B: 'a + Clone,
798			C: 'a + Clone,
799			D: 'a + Clone,
800			F: Applicative,
801		>(
802			f: impl Fn(A) -> Apply!(<F as Kind!( type Of<'a, T: 'a>: 'a; )>::Of<'a, C>) + 'a,
803			g: impl Fn(B) -> Apply!(<F as Kind!( type Of<'a, T: 'a>: 'a; )>::Of<'a, D>) + 'a,
804			p: Apply!(<Self as Kind!( type Of<'a, A: 'a, B: 'a>: 'a; )>::Of<'a, A, B>),
805		) -> Apply!(<F as Kind!( type Of<'a, T: 'a>: 'a; )>::Of<'a, Apply!(<Self as Kind!( type Of<'a, A: 'a, B: 'a>: 'a; )>::Of<'a, C, D>)>)
806		{
807			p.bi_traverse::<C, D, F>(f, g)
808		}
809	}
810
811	// PairFirstAppliedBrand<First> (Functor over Second)
812
813	impl_kind! {
814		#[multi_brand]
815		#[document_type_parameters("The type of the first value in the pair.")]
816		impl<First: 'static> for PairFirstAppliedBrand<First> {
817			type Of<'a, A: 'a>: 'a = Pair<First, A>;
818		}
819	}
820
821	#[document_type_parameters("The type of the first value in the pair.")]
822	impl<First: 'static> Functor for PairFirstAppliedBrand<First> {
823		/// Maps a function over the second value in the pair.
824		///
825		/// This method applies a function to the second value inside the pair, producing a new pair with the transformed second value. The first value remains unchanged.
826		#[document_signature]
827		///
828		#[document_type_parameters(
829			"The lifetime of the values.",
830			"The type of the second value.",
831			"The type of the result of applying the function."
832		)]
833		///
834		#[document_parameters(
835			"The function to apply to the second value.",
836			"The pair to map over."
837		)]
838		///
839		#[document_returns(
840			"A new pair containing the result of applying the function to the second value."
841		)]
842		#[document_examples]
843		///
844		/// ```
845		/// use fp_library::{
846		/// 	brands::*,
847		/// 	functions::*,
848		/// 	types::*,
849		/// };
850		///
851		/// assert_eq!(
852		/// 	explicit::map::<PairFirstAppliedBrand<_>, _, _, _, _>(|x: i32| x * 2, Pair(1, 5)),
853		/// 	Pair(1, 10)
854		/// );
855		/// ```
856		fn map<'a, A: 'a, B: 'a>(
857			func: impl Fn(A) -> B + 'a,
858			fa: Apply!(<Self as Kind!( type Of<'a, T: 'a>: 'a; )>::Of<'a, A>),
859		) -> Apply!(<Self as Kind!( type Of<'a, T: 'a>: 'a; )>::Of<'a, B>) {
860			fa.map_second(func)
861		}
862	}
863
864	#[document_type_parameters("The type of the first value in the pair.")]
865	impl<First: Clone + 'static> Lift for PairFirstAppliedBrand<First>
866	where
867		First: Semigroup,
868	{
869		/// Lifts a binary function into the pair context (over second).
870		///
871		/// This method lifts a binary function to operate on the second values within the pair context. The first values are combined using their `Semigroup` implementation.
872		#[document_signature]
873		///
874		#[document_type_parameters(
875			"The lifetime of the values.",
876			"The type of the first second value.",
877			"The type of the second second value.",
878			"The type of the result second value."
879		)]
880		///
881		#[document_parameters(
882			"The binary function to apply to the second values.",
883			"The first pair.",
884			"The second pair."
885		)]
886		///
887		#[document_returns(
888			"A new pair where the first values are combined using `Semigroup::append` and the second values are combined using `f`."
889		)]
890		#[document_examples]
891		///
892		/// ```
893		/// use fp_library::{
894		/// 	brands::*,
895		/// 	functions::*,
896		/// 	types::*,
897		/// };
898		///
899		/// assert_eq!(
900		/// 	explicit::lift2::<PairFirstAppliedBrand<String>, _, _, _, _, _, _>(
901		/// 		|x, y| x + y,
902		/// 		Pair("a".to_string(), 1),
903		/// 		Pair("b".to_string(), 2)
904		/// 	),
905		/// 	Pair("ab".to_string(), 3)
906		/// );
907		/// ```
908		fn lift2<'a, A, B, C>(
909			func: impl Fn(A, B) -> C + 'a,
910			fa: Apply!(<Self as Kind!( type Of<'a, T: 'a>: 'a; )>::Of<'a, A>),
911			fb: Apply!(<Self as Kind!( type Of<'a, T: 'a>: 'a; )>::Of<'a, B>),
912		) -> Apply!(<Self as Kind!( type Of<'a, T: 'a>: 'a; )>::Of<'a, C>)
913		where
914			A: Clone + 'a,
915			B: Clone + 'a,
916			C: 'a, {
917			let Pair(fa_first, fa_second) = fa;
918			let Pair(fb_first, fb_second) = fb;
919			Pair(Semigroup::append(fa_first, fb_first), func(fa_second, fb_second))
920		}
921	}
922
923	#[document_type_parameters("The type of the first value in the pair.")]
924	impl<First: Clone + 'static> Pointed for PairFirstAppliedBrand<First>
925	where
926		First: Monoid,
927	{
928		/// Wraps a value in a pair (with empty first).
929		///
930		/// This method wraps a value in a pair, using the `Monoid::empty()` value for the first element.
931		#[document_signature]
932		///
933		#[document_type_parameters("The lifetime of the value.", "The type of the value to wrap.")]
934		///
935		#[document_parameters("The value to wrap.")]
936		///
937		#[document_returns("A pair containing the empty value of the first type and `a`.")]
938		///
939		#[document_examples]
940		///
941		/// ```
942		/// use fp_library::{
943		/// 	brands::*,
944		/// 	functions::*,
945		/// 	types::*,
946		/// };
947		///
948		/// assert_eq!(pure::<PairFirstAppliedBrand<String>, _>(5), Pair("".to_string(), 5));
949		/// ```
950		fn pure<'a, A: 'a>(a: A) -> Apply!(<Self as Kind!( type Of<'a, T: 'a>: 'a; )>::Of<'a, A>) {
951			Pair(Monoid::empty(), a)
952		}
953	}
954
955	#[document_type_parameters("The type of the first value in the pair.")]
956	impl<First: Clone + Semigroup + 'static> ApplyFirst for PairFirstAppliedBrand<First> {}
957
958	#[document_type_parameters("The type of the first value in the pair.")]
959	impl<First: Clone + Semigroup + 'static> ApplySecond for PairFirstAppliedBrand<First> {}
960
961	#[document_type_parameters("The type of the first value in the pair.")]
962	impl<First: Clone + 'static> Semiapplicative for PairFirstAppliedBrand<First>
963	where
964		First: Semigroup,
965	{
966		/// Applies a wrapped function to a wrapped value (over second).
967		///
968		/// This method applies a function wrapped in a pair to a value wrapped in a pair. The first values are combined using their `Semigroup` implementation.
969		#[document_signature]
970		///
971		#[document_type_parameters(
972			"The lifetime of the values.",
973			"The brand of the cloneable function wrapper.",
974			"The type of the input value.",
975			"The type of the output value."
976		)]
977		///
978		#[document_parameters(
979			"The pair containing the function.",
980			"The pair containing the value."
981		)]
982		///
983		#[document_returns(
984			"A new pair where the first values are combined and the function is applied to the second value."
985		)]
986		#[document_examples]
987		///
988		/// ```
989		/// use fp_library::{
990		/// 	brands::*,
991		/// 	classes::semiapplicative::apply as explicit_apply,
992		/// 	functions::*,
993		/// 	types::*,
994		/// };
995		///
996		/// let f = Pair("a".to_string(), lift_fn_new::<RcFnBrand, _, _>(|x: i32| x * 2));
997		/// assert_eq!(
998		/// 	explicit_apply::<RcFnBrand, PairFirstAppliedBrand<String>, _, _>(
999		/// 		f,
1000		/// 		Pair("b".to_string(), 5)
1001		/// 	),
1002		/// 	Pair("ab".to_string(), 10)
1003		/// );
1004		/// ```
1005		fn apply<'a, FnBrand: 'a + CloneFn, A: 'a + Clone, B: 'a>(
1006			ff: Apply!(<Self as Kind!( type Of<'a, T: 'a>: 'a; )>::Of<'a, <FnBrand as CloneFn>::Of<'a, A, B>>),
1007			fa: Apply!(<Self as Kind!( type Of<'a, T: 'a>: 'a; )>::Of<'a, A>),
1008		) -> Apply!(<Self as Kind!( type Of<'a, T: 'a>: 'a; )>::Of<'a, B>) {
1009			Pair(Semigroup::append(ff.0, fa.0), ff.1(fa.1))
1010		}
1011	}
1012
1013	#[document_type_parameters("The type of the first value in the pair.")]
1014	impl<First: Clone + 'static> Semimonad for PairFirstAppliedBrand<First>
1015	where
1016		First: Semigroup,
1017	{
1018		/// Chains pair computations (over second).
1019		///
1020		/// This method chains two computations, where the second computation depends on the result of the first. The first values are combined using their `Semigroup` implementation.
1021		#[document_signature]
1022		///
1023		#[document_type_parameters(
1024			"The lifetime of the values.",
1025			"The type of the result of the first computation.",
1026			"The type of the result of the second computation."
1027		)]
1028		///
1029		#[document_parameters("The first pair.", "The function to apply to the second value.")]
1030		///
1031		#[document_returns("A new pair where the first values are combined.")]
1032		///
1033		#[document_examples]
1034		///
1035		/// ```
1036		/// use fp_library::{
1037		/// 	brands::*,
1038		/// 	functions::*,
1039		/// 	types::*,
1040		/// };
1041		///
1042		/// assert_eq!(
1043		/// 	explicit::bind::<PairFirstAppliedBrand<String>, _, _, _, _>(
1044		/// 		Pair("a".to_string(), 5),
1045		/// 		|x| { Pair("b".to_string(), x * 2) }
1046		/// 	),
1047		/// 	Pair("ab".to_string(), 10)
1048		/// );
1049		/// ```
1050		fn bind<'a, A: 'a, B: 'a>(
1051			ma: Apply!(<Self as Kind!( type Of<'a, T: 'a>: 'a; )>::Of<'a, A>),
1052			func: impl Fn(A) -> Apply!(<Self as Kind!( type Of<'a, T: 'a>: 'a; )>::Of<'a, B>) + 'a,
1053		) -> Apply!(<Self as Kind!( type Of<'a, T: 'a>: 'a; )>::Of<'a, B>) {
1054			ma.bind(func)
1055		}
1056	}
1057
1058	/// [`MonadRec`] implementation for [`PairFirstAppliedBrand`].
1059	#[document_type_parameters("The type of the first value in the pair.")]
1060	impl<First: Clone + 'static> MonadRec for PairFirstAppliedBrand<First>
1061	where
1062		First: Monoid,
1063	{
1064		/// Performs tail-recursive monadic computation over the second value, accumulating the first.
1065		///
1066		/// Iteratively applies the step function. Each iteration produces a pair
1067		/// whose first value is combined with the running accumulator via
1068		/// [`Semigroup::append`]. If the step returns `ControlFlow::Continue(a)`, the loop
1069		/// continues with the new state. If it returns `ControlFlow::Break(b)`, the
1070		/// computation completes with the accumulated first value and `b`.
1071		#[document_signature]
1072		///
1073		#[document_type_parameters(
1074			"The lifetime of the computation.",
1075			"The type of the initial value and loop state.",
1076			"The type of the result."
1077		)]
1078		///
1079		#[document_parameters("The step function.", "The initial value.")]
1080		///
1081		#[document_returns("A pair with the accumulated first value and the final result.")]
1082		///
1083		#[document_examples]
1084		///
1085		/// ```
1086		/// use {
1087		/// 	core::ops::ControlFlow,
1088		/// 	fp_library::{
1089		/// 		brands::*,
1090		/// 		functions::*,
1091		/// 		types::*,
1092		/// 	},
1093		/// };
1094		///
1095		/// let result = tail_rec_m::<PairFirstAppliedBrand<String>, _, _>(
1096		/// 	|n| {
1097		/// 		if n < 3 {
1098		/// 			Pair(format!("{n},"), ControlFlow::Continue(n + 1))
1099		/// 		} else {
1100		/// 			Pair(format!("{n}"), ControlFlow::Break(n))
1101		/// 		}
1102		/// 	},
1103		/// 	0,
1104		/// );
1105		/// assert_eq!(result, Pair("0,1,2,3".to_string(), 3));
1106		/// ```
1107		fn tail_rec_m<'a, A: 'a, B: 'a>(
1108			func: impl Fn(
1109				A,
1110			)
1111				-> Apply!(<Self as Kind!( type Of<'a, T: 'a>: 'a; )>::Of<'a, ControlFlow<B, A>>)
1112			+ 'a,
1113			initial: A,
1114		) -> Apply!(<Self as Kind!( type Of<'a, T: 'a>: 'a; )>::Of<'a, B>) {
1115			let mut acc: First = Monoid::empty();
1116			let mut current = initial;
1117			loop {
1118				let Pair(first, step) = func(current);
1119				acc = Semigroup::append(acc, first);
1120				match step {
1121					ControlFlow::Continue(next) => current = next,
1122					ControlFlow::Break(b) => return Pair(acc, b),
1123				}
1124			}
1125		}
1126	}
1127
1128	#[document_type_parameters("The type of the first value in the pair.")]
1129	impl<First: 'static> Foldable for PairFirstAppliedBrand<First> {
1130		/// Folds the pair from the right (over second).
1131		///
1132		/// This method performs a right-associative fold of the pair (over second).
1133		#[document_signature]
1134		///
1135		#[document_type_parameters(
1136			"The lifetime of the values.",
1137			"The brand of the cloneable function to use.",
1138			"The type of the elements in the structure.",
1139			"The type of the accumulator."
1140		)]
1141		///
1142		#[document_parameters("The folding function.", "The initial value.", "The pair to fold.")]
1143		///
1144		#[document_returns("`func(a, initial)`.")]
1145		///
1146		#[document_examples]
1147		///
1148		/// ```
1149		/// use fp_library::{
1150		/// 	brands::*,
1151		/// 	functions::*,
1152		/// 	types::*,
1153		/// };
1154		///
1155		/// assert_eq!(
1156		/// 	explicit::fold_right::<RcFnBrand, PairFirstAppliedBrand<()>, _, _, _, _>(
1157		/// 		|x, acc| x + acc,
1158		/// 		0,
1159		/// 		Pair((), 5)
1160		/// 	),
1161		/// 	5
1162		/// );
1163		/// ```
1164		fn fold_right<'a, FnBrand, A: 'a + Clone, B: 'a>(
1165			func: impl Fn(A, B) -> B + 'a,
1166			initial: B,
1167			fa: Apply!(<Self as Kind!( type Of<'a, T: 'a>: 'a; )>::Of<'a, A>),
1168		) -> B
1169		where
1170			FnBrand: CloneFn + 'a, {
1171			func(fa.1, initial)
1172		}
1173
1174		/// Folds the pair from the left (over second).
1175		///
1176		/// This method performs a left-associative fold of the pair (over second).
1177		#[document_signature]
1178		///
1179		#[document_type_parameters(
1180			"The lifetime of the values.",
1181			"The brand of the cloneable function to use.",
1182			"The type of the elements in the structure.",
1183			"The type of the accumulator."
1184		)]
1185		///
1186		#[document_parameters(
1187			"The function to apply to the accumulator and each element.",
1188			"The initial value of the accumulator.",
1189			"The identity to fold."
1190		)]
1191		///
1192		#[document_returns("`func(initial, a)`.")]
1193		#[document_examples]
1194		///
1195		/// ```
1196		/// use fp_library::{
1197		/// 	brands::*,
1198		/// 	functions::*,
1199		/// 	types::*,
1200		/// };
1201		///
1202		/// assert_eq!(
1203		/// 	explicit::fold_left::<RcFnBrand, PairFirstAppliedBrand<()>, _, _, _, _>(
1204		/// 		|acc, x| acc + x,
1205		/// 		0,
1206		/// 		Pair((), 5)
1207		/// 	),
1208		/// 	5
1209		/// );
1210		/// ```
1211		fn fold_left<'a, FnBrand, A: 'a + Clone, B: 'a>(
1212			func: impl Fn(B, A) -> B + 'a,
1213			initial: B,
1214			fa: Apply!(<Self as Kind!( type Of<'a, T: 'a>: 'a; )>::Of<'a, A>),
1215		) -> B
1216		where
1217			FnBrand: CloneFn + 'a, {
1218			func(initial, fa.1)
1219		}
1220
1221		/// Maps the value to a monoid and returns it (over second).
1222		///
1223		/// This method maps the element of the pair to a monoid and then returns it (over second).
1224		#[document_signature]
1225		///
1226		#[document_type_parameters(
1227			"The lifetime of the values.",
1228			"The brand of the cloneable function to use.",
1229			"The type of the elements in the structure.",
1230			"The type of the monoid."
1231		)]
1232		///
1233		#[document_parameters("The mapping function.", "The pair to fold.")]
1234		///
1235		#[document_returns("`func(a)`.")]
1236		///
1237		#[document_examples]
1238		///
1239		/// ```
1240		/// use fp_library::{
1241		/// 	brands::*,
1242		/// 	functions::*,
1243		/// 	types::*,
1244		/// };
1245		///
1246		/// assert_eq!(
1247		/// 	explicit::fold_map::<RcFnBrand, PairFirstAppliedBrand<()>, _, _, _, _>(
1248		/// 		|x: i32| x.to_string(),
1249		/// 		Pair((), 5)
1250		/// 	),
1251		/// 	"5".to_string()
1252		/// );
1253		/// ```
1254		fn fold_map<'a, FnBrand, A: 'a + Clone, M>(
1255			func: impl Fn(A) -> M + 'a,
1256			fa: Apply!(<Self as Kind!( type Of<'a, T: 'a>: 'a; )>::Of<'a, A>),
1257		) -> M
1258		where
1259			M: Monoid + 'a,
1260			FnBrand: CloneFn + 'a, {
1261			func(fa.1)
1262		}
1263	}
1264
1265	#[document_type_parameters("The type of the first value in the pair.")]
1266	impl<First: Clone + 'static> Traversable for PairFirstAppliedBrand<First> {
1267		/// Traverses the pair with an applicative function (over second).
1268		///
1269		/// This method maps the element of the pair to a computation, evaluates it, and combines the result into an applicative context (over second).
1270		#[document_signature]
1271		///
1272		#[document_type_parameters(
1273			"The lifetime of the values.",
1274			"The type of the elements in the traversable structure.",
1275			"The type of the elements in the resulting traversable structure.",
1276			"The applicative context."
1277		)]
1278		///
1279		#[document_parameters(
1280			"The function to apply to each element, returning a value in an applicative context.",
1281			"The pair to traverse."
1282		)]
1283		///
1284		#[document_returns("The pair wrapped in the applicative context.")]
1285		#[document_examples]
1286		///
1287		/// ```
1288		/// use fp_library::{
1289		/// 	brands::*,
1290		/// 	functions::*,
1291		/// 	types::*,
1292		/// };
1293		///
1294		/// assert_eq!(
1295		/// 	explicit::traverse::<RcFnBrand, PairFirstAppliedBrand<()>, _, _, OptionBrand, _, _>(
1296		/// 		|x| Some(x * 2),
1297		/// 		Pair((), 5)
1298		/// 	),
1299		/// 	Some(Pair((), 10))
1300		/// );
1301		/// ```
1302		fn traverse<'a, A: 'a + Clone, B: 'a + Clone, F: Applicative>(
1303			func: impl Fn(A) -> Apply!(<F as Kind!( type Of<'a, T: 'a>: 'a; )>::Of<'a, B>) + 'a,
1304			ta: Apply!(<Self as Kind!( type Of<'a, T: 'a>: 'a; )>::Of<'a, A>),
1305		) -> Apply!(<F as Kind!( type Of<'a, T: 'a>: 'a; )>::Of<'a, Apply!(<Self as Kind!( type Of<'a, T: 'a>: 'a; )>::Of<'a, B>)>)
1306		where
1307			Apply!(<Self as Kind!( type Of<'a, T: 'a>: 'a; )>::Of<'a, B>): Clone, {
1308			let Pair(first, second) = ta;
1309			F::map(move |b| Pair(first.clone(), b), func(second))
1310		}
1311
1312		/// Sequences a pair of applicative (over second).
1313		///
1314		/// This method evaluates the computation inside the pair and accumulates the result into an applicative context (over second).
1315		#[document_signature]
1316		///
1317		#[document_type_parameters(
1318			"The lifetime of the values.",
1319			"The type of the elements in the traversable structure.",
1320			"The applicative context."
1321		)]
1322		///
1323		#[document_parameters("The pair containing the applicative value.")]
1324		///
1325		#[document_returns("The pair wrapped in the applicative context.")]
1326		///
1327		#[document_examples]
1328		///
1329		/// ```
1330		/// use fp_library::{
1331		/// 	brands::*,
1332		/// 	functions::*,
1333		/// 	types::*,
1334		/// };
1335		///
1336		/// assert_eq!(
1337		/// 	sequence::<PairFirstAppliedBrand<()>, _, OptionBrand>(Pair((), Some(5))),
1338		/// 	Some(Pair((), 5))
1339		/// );
1340		/// ```
1341		fn sequence<'a, A: 'a + Clone, F: Applicative>(
1342			ta: Apply!(<Self as Kind!( type Of<'a, T: 'a>: 'a; )>::Of<'a, Apply!(<F as Kind!( type Of<'a, T: 'a>: 'a; )>::Of<'a, A>)>)
1343		) -> Apply!(<F as Kind!( type Of<'a, T: 'a>: 'a; )>::Of<'a, Apply!(<Self as Kind!( type Of<'a, T: 'a>: 'a; )>::Of<'a, A>)>)
1344		where
1345			Apply!(<F as Kind!( type Of<'a, T: 'a>: 'a; )>::Of<'a, A>): Clone,
1346			Apply!(<Self as Kind!( type Of<'a, T: 'a>: 'a; )>::Of<'a, A>): Clone, {
1347			let Pair(first, second) = ta;
1348			F::map(move |a| Pair(first.clone(), a), second)
1349		}
1350	}
1351
1352	// -- By-reference trait implementations for PairFirstAppliedBrand --
1353
1354	#[document_type_parameters("The type of the first value in the pair.")]
1355	impl<First: Clone + 'static> RefFunctor for PairFirstAppliedBrand<First> {
1356		/// Maps a function over the second value in the pair by reference.
1357		#[document_signature]
1358		#[document_type_parameters("The lifetime.", "The input type.", "The output type.")]
1359		#[document_parameters("The function.", "The pair.")]
1360		#[document_returns("A new pair with the mapped second value.")]
1361		#[document_examples]
1362		///
1363		/// ```
1364		/// use fp_library::{
1365		/// 	brands::*,
1366		/// 	functions::*,
1367		/// 	types::*,
1368		/// };
1369		/// assert_eq!(
1370		/// 	explicit::map::<PairFirstAppliedBrand<_>, _, _, _, _>(|x: &i32| *x * 2, &Pair(1, 5)),
1371		/// 	Pair(1, 10)
1372		/// );
1373		/// ```
1374		fn ref_map<'a, A: 'a, B: 'a>(
1375			func: impl Fn(&A) -> B + 'a,
1376			fa: &Apply!(<Self as Kind!( type Of<'a, T: 'a>: 'a; )>::Of<'a, A>),
1377		) -> Apply!(<Self as Kind!( type Of<'a, T: 'a>: 'a; )>::Of<'a, B>) {
1378			Pair(fa.0.clone(), func(&fa.1))
1379		}
1380	}
1381
1382	#[document_type_parameters("The type of the first value in the pair.")]
1383	impl<First: Clone + 'static> RefFoldable for PairFirstAppliedBrand<First> {
1384		/// Folds the pair by reference (over second).
1385		#[document_signature]
1386		#[document_type_parameters(
1387			"The lifetime.",
1388			"The brand.",
1389			"The element type.",
1390			"The monoid type."
1391		)]
1392		#[document_parameters("The mapping function.", "The pair.")]
1393		#[document_returns("The monoid value.")]
1394		#[document_examples]
1395		///
1396		/// ```
1397		/// use fp_library::{
1398		/// 	brands::*,
1399		/// 	functions::*,
1400		/// 	types::*,
1401		/// };
1402		/// let result = explicit::fold_map::<RcFnBrand, PairFirstAppliedBrand<()>, _, _, _, _>(
1403		/// 	|x: &i32| x.to_string(),
1404		/// 	&Pair((), 5),
1405		/// );
1406		/// assert_eq!(result, "5");
1407		/// ```
1408		fn ref_fold_map<'a, FnBrand, A: 'a + Clone, M>(
1409			func: impl Fn(&A) -> M + 'a,
1410			fa: &Apply!(<Self as Kind!( type Of<'a, T: 'a>: 'a; )>::Of<'a, A>),
1411		) -> M
1412		where
1413			FnBrand: LiftFn + 'a,
1414			M: Monoid + 'a, {
1415			func(&fa.1)
1416		}
1417	}
1418
1419	#[document_type_parameters("The type of the first value in the pair.")]
1420	impl<First: Clone + 'static> RefTraversable for PairFirstAppliedBrand<First> {
1421		/// Traverses the pair by reference (over second).
1422		#[document_signature]
1423		#[document_type_parameters(
1424			"The lifetime.",
1425			"The brand.",
1426			"The input type.",
1427			"The output type.",
1428			"The applicative."
1429		)]
1430		#[document_parameters("The function.", "The pair.")]
1431		#[document_returns("The traversed result.")]
1432		#[document_examples]
1433		///
1434		/// ```
1435		/// use fp_library::{
1436		/// 	brands::*,
1437		/// 	functions::*,
1438		/// 	types::*,
1439		/// };
1440		/// let result: Option<Pair<(), String>> =
1441		/// 	ref_traverse::<PairFirstAppliedBrand<()>, RcFnBrand, _, _, OptionBrand>(
1442		/// 		|x: &i32| Some(x.to_string()),
1443		/// 		&Pair((), 42),
1444		/// 	);
1445		/// assert_eq!(result, Some(Pair((), "42".to_string())));
1446		/// ```
1447		fn ref_traverse<'a, FnBrand, A: 'a + Clone, B: 'a + Clone, F: Applicative>(
1448			func: impl Fn(&A) -> Apply!(<F as Kind!( type Of<'a, T: 'a>: 'a; )>::Of<'a, B>) + 'a,
1449			ta: &Apply!(<Self as Kind!( type Of<'a, T: 'a>: 'a; )>::Of<'a, A>),
1450		) -> Apply!(<F as Kind!( type Of<'a, T: 'a>: 'a; )>::Of<'a, Apply!(<Self as Kind!( type Of<'a, T: 'a>: 'a; )>::Of<'a, B>)>)
1451		where
1452			FnBrand: LiftFn + 'a,
1453			Apply!(<Self as Kind!( type Of<'a, T: 'a>: 'a; )>::Of<'a, B>): Clone,
1454			Apply!(<F as Kind!( type Of<'a, T: 'a>: 'a; )>::Of<'a, B>): Clone, {
1455			let first = ta.0.clone();
1456			F::map(move |b| Pair(first.clone(), b), func(&ta.1))
1457		}
1458	}
1459
1460	#[document_type_parameters("The type of the first value in the pair.")]
1461	impl<First: Clone + 'static> RefPointed for PairFirstAppliedBrand<First>
1462	where
1463		First: Monoid,
1464	{
1465		/// Creates a pair from a reference by cloning (with empty first).
1466		#[document_signature]
1467		#[document_type_parameters("The lifetime.", "The value type.")]
1468		#[document_parameters("The reference to wrap.")]
1469		#[document_returns("A pair containing `Monoid::empty()` and a clone of the value.")]
1470		#[document_examples]
1471		///
1472		/// ```
1473		/// use fp_library::{
1474		/// 	brands::*,
1475		/// 	functions::*,
1476		/// 	types::*,
1477		/// };
1478		///
1479		/// let x = 42;
1480		/// let result: Pair<String, i32> = ref_pure::<PairFirstAppliedBrand<String>, _>(&x);
1481		/// assert_eq!(result, Pair("".to_string(), 42));
1482		/// ```
1483		fn ref_pure<'a, A: Clone + 'a>(
1484			a: &A
1485		) -> Apply!(<Self as Kind!( type Of<'a, T: 'a>: 'a; )>::Of<'a, A>) {
1486			Pair(Monoid::empty(), a.clone())
1487		}
1488	}
1489
1490	#[document_type_parameters("The type of the first value in the pair.")]
1491	impl<First: Clone + 'static> RefLift for PairFirstAppliedBrand<First>
1492	where
1493		First: Semigroup,
1494	{
1495		/// Combines two pairs with a by-reference binary function (over second).
1496		#[document_signature]
1497		#[document_type_parameters("The lifetime.", "First input.", "Second input.", "Output.")]
1498		#[document_parameters("The binary function.", "The first pair.", "The second pair.")]
1499		#[document_returns("A pair with combined first values and the function result.")]
1500		#[document_examples]
1501		///
1502		/// ```
1503		/// use fp_library::{
1504		/// 	brands::*,
1505		/// 	functions::*,
1506		/// 	types::*,
1507		/// };
1508		///
1509		/// let result = explicit::lift2::<PairFirstAppliedBrand<String>, _, _, _, _, _, _>(
1510		/// 	|a: &i32, b: &i32| *a + *b,
1511		/// 	&Pair("a".to_string(), 1),
1512		/// 	&Pair("b".to_string(), 2),
1513		/// );
1514		/// assert_eq!(result, Pair("ab".to_string(), 3));
1515		/// ```
1516		fn ref_lift2<'a, A: 'a, B: 'a, C: 'a>(
1517			func: impl Fn(&A, &B) -> C + 'a,
1518			fa: &Apply!(<Self as Kind!( type Of<'a, T: 'a>: 'a; )>::Of<'a, A>),
1519			fb: &Apply!(<Self as Kind!( type Of<'a, T: 'a>: 'a; )>::Of<'a, B>),
1520		) -> Apply!(<Self as Kind!( type Of<'a, T: 'a>: 'a; )>::Of<'a, C>) {
1521			Pair(Semigroup::append(fa.0.clone(), fb.0.clone()), func(&fa.1, &fb.1))
1522		}
1523	}
1524
1525	#[document_type_parameters("The type of the first value in the pair.")]
1526	impl<First: Clone + 'static> RefSemiapplicative for PairFirstAppliedBrand<First>
1527	where
1528		First: Semigroup,
1529	{
1530		/// Applies a wrapped by-ref function to a pair value (over second).
1531		#[document_signature]
1532		#[document_type_parameters(
1533			"The lifetime.",
1534			"The function brand.",
1535			"The input type.",
1536			"The output type."
1537		)]
1538		#[document_parameters(
1539			"The pair containing the function.",
1540			"The pair containing the value."
1541		)]
1542		#[document_returns("A pair with combined first values and the function result.")]
1543		#[document_examples]
1544		///
1545		/// ```
1546		/// use fp_library::{
1547		/// 	brands::*,
1548		/// 	functions::*,
1549		/// 	types::*,
1550		/// };
1551		///
1552		/// let f: std::rc::Rc<dyn Fn(&i32) -> i32> = std::rc::Rc::new(|x: &i32| *x * 2);
1553		/// let result = ref_apply::<RcFnBrand, PairFirstAppliedBrand<String>, _, _>(
1554		/// 	&Pair("a".to_string(), f),
1555		/// 	&Pair("b".to_string(), 5),
1556		/// );
1557		/// assert_eq!(result, Pair("ab".to_string(), 10));
1558		/// ```
1559		fn ref_apply<'a, FnBrand: 'a + CloneFn<Ref>, A: 'a, B: 'a>(
1560			ff: &Apply!(<Self as Kind!( type Of<'a, T: 'a>: 'a; )>::Of<'a, <FnBrand as CloneFn<Ref>>::Of<'a, A, B>>),
1561			fa: &Apply!(<Self as Kind!( type Of<'a, T: 'a>: 'a; )>::Of<'a, A>),
1562		) -> Apply!(<Self as Kind!( type Of<'a, T: 'a>: 'a; )>::Of<'a, B>) {
1563			Pair(Semigroup::append(ff.0.clone(), fa.0.clone()), (*ff.1)(&fa.1))
1564		}
1565	}
1566
1567	#[document_type_parameters("The type of the first value in the pair.")]
1568	impl<First: Clone + 'static> RefSemimonad for PairFirstAppliedBrand<First>
1569	where
1570		First: Semigroup,
1571	{
1572		/// Chains pair computations by reference (over second).
1573		#[document_signature]
1574		#[document_type_parameters("The lifetime.", "The input type.", "The output type.")]
1575		#[document_parameters("The input pair.", "The function to apply by reference.")]
1576		#[document_returns("A pair with combined first values.")]
1577		#[document_examples]
1578		///
1579		/// ```
1580		/// use fp_library::{
1581		/// 	brands::*,
1582		/// 	functions::*,
1583		/// 	types::*,
1584		/// };
1585		///
1586		/// let result: Pair<String, String> = explicit::bind::<PairFirstAppliedBrand<String>, _, _, _, _>(
1587		/// 	&Pair("a".to_string(), 42),
1588		/// 	|x: &i32| Pair("b".to_string(), x.to_string()),
1589		/// );
1590		/// assert_eq!(result, Pair("ab".to_string(), "42".to_string()));
1591		/// ```
1592		fn ref_bind<'a, A: 'a, B: 'a>(
1593			fa: &Apply!(<Self as Kind!( type Of<'a, T: 'a>: 'a; )>::Of<'a, A>),
1594			f: impl Fn(&A) -> Apply!(<Self as Kind!( type Of<'a, T: 'a>: 'a; )>::Of<'a, B>) + 'a,
1595		) -> Apply!(<Self as Kind!( type Of<'a, T: 'a>: 'a; )>::Of<'a, B>) {
1596			let Pair(next_first, next_second) = f(&fa.1);
1597			Pair(Semigroup::append(fa.0.clone(), next_first), next_second)
1598		}
1599	}
1600
1601	// PairSecondAppliedBrand<Second> (Functor over First)
1602
1603	impl_kind! {
1604		#[multi_brand]
1605		#[document_type_parameters("The type of the second value in the pair.")]
1606		impl<Second: 'static> for PairSecondAppliedBrand<Second> {
1607			type Of<'a, A: 'a>: 'a = Pair<A, Second>;
1608		}
1609	}
1610
1611	#[document_type_parameters("The type of the second value in the pair.")]
1612	impl<Second: 'static> Functor for PairSecondAppliedBrand<Second> {
1613		/// Maps a function over the first value in the pair.
1614		///
1615		/// This method applies a function to the first value inside the pair, producing a new pair with the transformed first value. The second value remains unchanged.
1616		#[document_signature]
1617		///
1618		#[document_type_parameters(
1619			"The lifetime of the values.",
1620			"The type of the first value.",
1621			"The type of the result of applying the function."
1622		)]
1623		///
1624		#[document_parameters("The function to apply to the first value.", "The pair to map over.")]
1625		///
1626		#[document_returns(
1627			"A new pair containing the result of applying the function to the first value."
1628		)]
1629		///
1630		#[document_examples]
1631		///
1632		/// ```
1633		/// use fp_library::{
1634		/// 	brands::*,
1635		/// 	functions::*,
1636		/// 	types::*,
1637		/// };
1638		///
1639		/// assert_eq!(
1640		/// 	explicit::map::<PairSecondAppliedBrand<_>, _, _, _, _>(|x: i32| x * 2, Pair(5, 1)),
1641		/// 	Pair(10, 1)
1642		/// );
1643		/// ```
1644		fn map<'a, A: 'a, B: 'a>(
1645			func: impl Fn(A) -> B + 'a,
1646			fa: Apply!(<Self as Kind!( type Of<'a, T: 'a>: 'a; )>::Of<'a, A>),
1647		) -> Apply!(<Self as Kind!( type Of<'a, T: 'a>: 'a; )>::Of<'a, B>) {
1648			fa.map_first(func)
1649		}
1650	}
1651
1652	#[document_type_parameters("The type of the second value in the pair.")]
1653	impl<Second: Clone + 'static> Lift for PairSecondAppliedBrand<Second>
1654	where
1655		Second: Semigroup,
1656	{
1657		/// Lifts a binary function into the pair context (over first).
1658		///
1659		/// This method lifts a binary function to operate on the first values within the pair context. The second values are combined using their `Semigroup` implementation.
1660		#[document_signature]
1661		///
1662		#[document_type_parameters(
1663			"The lifetime of the values.",
1664			"The type of the first first value.",
1665			"The type of the second first value.",
1666			"The type of the result first value."
1667		)]
1668		///
1669		#[document_parameters(
1670			"The binary function to apply to the first values.",
1671			"The first pair.",
1672			"The second pair."
1673		)]
1674		///
1675		#[document_returns(
1676			"A new pair where the first values are combined using `f` and the second values are combined using `Semigroup::append`."
1677		)]
1678		#[document_examples]
1679		///
1680		/// ```
1681		/// use fp_library::{
1682		/// 	brands::*,
1683		/// 	functions::*,
1684		/// 	types::*,
1685		/// };
1686		///
1687		/// assert_eq!(
1688		/// 	explicit::lift2::<PairSecondAppliedBrand<String>, _, _, _, _, _, _>(
1689		/// 		|x, y| x + y,
1690		/// 		Pair(1, "a".to_string()),
1691		/// 		Pair(2, "b".to_string())
1692		/// 	),
1693		/// 	Pair(3, "ab".to_string())
1694		/// );
1695		/// ```
1696		fn lift2<'a, A, B, C>(
1697			func: impl Fn(A, B) -> C + 'a,
1698			fa: Apply!(<Self as Kind!( type Of<'a, T: 'a>: 'a; )>::Of<'a, A>),
1699			fb: Apply!(<Self as Kind!( type Of<'a, T: 'a>: 'a; )>::Of<'a, B>),
1700		) -> Apply!(<Self as Kind!( type Of<'a, T: 'a>: 'a; )>::Of<'a, C>)
1701		where
1702			A: Clone + 'a,
1703			B: Clone + 'a,
1704			C: 'a, {
1705			Pair(func(fa.0, fb.0), Semigroup::append(fa.1, fb.1))
1706		}
1707	}
1708
1709	#[document_type_parameters("The type of the second value in the pair.")]
1710	impl<Second: Clone + 'static> Pointed for PairSecondAppliedBrand<Second>
1711	where
1712		Second: Monoid,
1713	{
1714		/// Wraps a value in a pair (with empty second).
1715		///
1716		/// This method wraps a value in a pair, using the `Monoid::empty()` value for the second element.
1717		#[document_signature]
1718		///
1719		#[document_type_parameters("The lifetime of the value.", "The type of the value to wrap.")]
1720		///
1721		#[document_parameters("The value to wrap.")]
1722		///
1723		#[document_returns("A pair containing `a` and the empty value of the second type.")]
1724		///
1725		#[document_examples]
1726		///
1727		/// ```
1728		/// use fp_library::{
1729		/// 	brands::*,
1730		/// 	functions::*,
1731		/// 	types::*,
1732		/// };
1733		///
1734		/// assert_eq!(pure::<PairSecondAppliedBrand<String>, _>(5), Pair(5, "".to_string()));
1735		/// ```
1736		fn pure<'a, A: 'a>(a: A) -> Apply!(<Self as Kind!( type Of<'a, T: 'a>: 'a; )>::Of<'a, A>) {
1737			Pair(a, Monoid::empty())
1738		}
1739	}
1740
1741	#[document_type_parameters("The type of the second value in the pair.")]
1742	impl<Second: Clone + Semigroup + 'static> ApplyFirst for PairSecondAppliedBrand<Second> {}
1743
1744	#[document_type_parameters("The type of the second value in the pair.")]
1745	impl<Second: Clone + Semigroup + 'static> ApplySecond for PairSecondAppliedBrand<Second> {}
1746
1747	#[document_type_parameters("The type of the second value in the pair.")]
1748	impl<Second: Clone + 'static> Semiapplicative for PairSecondAppliedBrand<Second>
1749	where
1750		Second: Semigroup,
1751	{
1752		/// Applies a wrapped function to a wrapped value (over first).
1753		///
1754		/// This method applies a function wrapped in a result (as error) to a value wrapped in a result (as error).
1755		#[document_signature]
1756		///
1757		#[document_type_parameters(
1758			"The lifetime of the values.",
1759			"The brand of the cloneable function wrapper.",
1760			"The type of the input value.",
1761			"The type of the output value."
1762		)]
1763		///
1764		#[document_parameters(
1765			"The pair containing the function (in Err).",
1766			"The pair containing the value (in Err)."
1767		)]
1768		///
1769		#[document_returns(
1770			"`Err(f(a))` if both are `Err`, otherwise the first success encountered."
1771		)]
1772		#[document_examples]
1773		///
1774		/// ```
1775		/// use fp_library::{
1776		/// 	brands::*,
1777		/// 	classes::semiapplicative::apply as explicit_apply,
1778		/// 	functions::*,
1779		/// 	types::*,
1780		/// };
1781		///
1782		/// let f = Pair(lift_fn_new::<RcFnBrand, _, _>(|x: i32| x * 2), "a".to_string());
1783		/// assert_eq!(
1784		/// 	explicit_apply::<RcFnBrand, PairSecondAppliedBrand<String>, _, _>(
1785		/// 		f,
1786		/// 		Pair(5, "b".to_string())
1787		/// 	),
1788		/// 	Pair(10, "ab".to_string())
1789		/// );
1790		/// ```
1791		fn apply<'a, FnBrand: 'a + CloneFn, A: 'a + Clone, B: 'a>(
1792			ff: Apply!(<Self as Kind!( type Of<'a, T: 'a>: 'a; )>::Of<'a, <FnBrand as CloneFn>::Of<'a, A, B>>),
1793			fa: Apply!(<Self as Kind!( type Of<'a, T: 'a>: 'a; )>::Of<'a, A>),
1794		) -> Apply!(<Self as Kind!( type Of<'a, T: 'a>: 'a; )>::Of<'a, B>) {
1795			Pair(ff.0(fa.0), Semigroup::append(ff.1, fa.1))
1796		}
1797	}
1798
1799	#[document_type_parameters("The type of the second value in the pair.")]
1800	impl<Second: Clone + 'static> Semimonad for PairSecondAppliedBrand<Second>
1801	where
1802		Second: Semigroup,
1803	{
1804		/// Chains pair computations (over first).
1805		///
1806		/// This method chains two computations, where the second computation depends on the result of the first (over error).
1807		#[document_signature]
1808		///
1809		#[document_type_parameters(
1810			"The lifetime of the values.",
1811			"The type of the result of the first computation.",
1812			"The type of the result of the second computation."
1813		)]
1814		///
1815		#[document_parameters("The first result.", "The function to apply to the error value.")]
1816		///
1817		#[document_returns(
1818			"The result of applying `f` to the error if `ma` is `Err`, otherwise the original success."
1819		)]
1820		///
1821		#[document_examples]
1822		///
1823		/// ```
1824		/// use fp_library::{
1825		/// 	brands::*,
1826		/// 	functions::*,
1827		/// 	types::*,
1828		/// };
1829		///
1830		/// assert_eq!(
1831		/// 	explicit::bind::<PairSecondAppliedBrand<String>, _, _, _, _>(
1832		/// 		Pair(5, "a".to_string()),
1833		/// 		|x| Pair(x * 2, "b".to_string())
1834		/// 	),
1835		/// 	Pair(10, "ab".to_string())
1836		/// );
1837		/// ```
1838		fn bind<'a, A: 'a, B: 'a>(
1839			ma: Apply!(<Self as Kind!( type Of<'a, T: 'a>: 'a; )>::Of<'a, A>),
1840			func: impl Fn(A) -> Apply!(<Self as Kind!( type Of<'a, T: 'a>: 'a; )>::Of<'a, B>) + 'a,
1841		) -> Apply!(<Self as Kind!( type Of<'a, T: 'a>: 'a; )>::Of<'a, B>) {
1842			ma.bind_first(func)
1843		}
1844	}
1845
1846	/// [`MonadRec`] implementation for [`PairSecondAppliedBrand`].
1847	#[document_type_parameters("The type of the second value in the pair.")]
1848	impl<Second: Clone + 'static> MonadRec for PairSecondAppliedBrand<Second>
1849	where
1850		Second: Monoid,
1851	{
1852		/// Performs tail-recursive monadic computation over the first value, accumulating the second.
1853		///
1854		/// Iteratively applies the step function. Each iteration produces a pair
1855		/// whose second value is combined with the running accumulator via
1856		/// [`Semigroup::append`]. If the step returns `ControlFlow::Continue(a)`, the loop
1857		/// continues with the new state. If it returns `ControlFlow::Break(b)`, the
1858		/// computation completes with `b` and the accumulated second value.
1859		#[document_signature]
1860		///
1861		#[document_type_parameters(
1862			"The lifetime of the computation.",
1863			"The type of the initial value and loop state.",
1864			"The type of the result."
1865		)]
1866		///
1867		#[document_parameters("The step function.", "The initial value.")]
1868		///
1869		#[document_returns("A pair with the final result and the accumulated second value.")]
1870		///
1871		#[document_examples]
1872		///
1873		/// ```
1874		/// use {
1875		/// 	core::ops::ControlFlow,
1876		/// 	fp_library::{
1877		/// 		brands::*,
1878		/// 		functions::*,
1879		/// 		types::*,
1880		/// 	},
1881		/// };
1882		///
1883		/// let result = tail_rec_m::<PairSecondAppliedBrand<String>, _, _>(
1884		/// 	|n| {
1885		/// 		if n < 3 {
1886		/// 			Pair(ControlFlow::Continue(n + 1), format!("{n},"))
1887		/// 		} else {
1888		/// 			Pair(ControlFlow::Break(n), format!("{n}"))
1889		/// 		}
1890		/// 	},
1891		/// 	0,
1892		/// );
1893		/// assert_eq!(result, Pair(3, "0,1,2,3".to_string()));
1894		/// ```
1895		fn tail_rec_m<'a, A: 'a, B: 'a>(
1896			func: impl Fn(
1897				A,
1898			)
1899				-> Apply!(<Self as Kind!( type Of<'a, T: 'a>: 'a; )>::Of<'a, ControlFlow<B, A>>)
1900			+ 'a,
1901			initial: A,
1902		) -> Apply!(<Self as Kind!( type Of<'a, T: 'a>: 'a; )>::Of<'a, B>) {
1903			let mut acc: Second = Monoid::empty();
1904			let mut current = initial;
1905			loop {
1906				let Pair(step, second) = func(current);
1907				acc = Semigroup::append(acc, second);
1908				match step {
1909					ControlFlow::Continue(next) => current = next,
1910					ControlFlow::Break(b) => return Pair(b, acc),
1911				}
1912			}
1913		}
1914	}
1915
1916	#[document_type_parameters("The type of the second value in the pair.")]
1917	impl<Second: 'static> Foldable for PairSecondAppliedBrand<Second> {
1918		/// Folds the pair from the right (over first).
1919		///
1920		/// This method performs a right-associative fold of the result (over error).
1921		#[document_signature]
1922		///
1923		#[document_type_parameters(
1924			"The lifetime of the values.",
1925			"The brand of the cloneable function to use.",
1926			"The type of the elements in the structure.",
1927			"The type of the accumulator."
1928		)]
1929		///
1930		#[document_parameters("The folding function.", "The initial value.", "The result to fold.")]
1931		///
1932		#[document_returns("`func(a, initial)` if `fa` is `Err(a)`, otherwise `initial`.")]
1933		///
1934		#[document_examples]
1935		///
1936		/// ```
1937		/// use fp_library::{
1938		/// 	brands::*,
1939		/// 	functions::*,
1940		/// 	types::*,
1941		/// };
1942		///
1943		/// assert_eq!(
1944		/// 	explicit::fold_right::<RcFnBrand, PairSecondAppliedBrand<()>, _, _, _, _>(
1945		/// 		|x, acc| x + acc,
1946		/// 		0,
1947		/// 		Pair(5, ())
1948		/// 	),
1949		/// 	5
1950		/// );
1951		/// ```
1952		fn fold_right<'a, FnBrand, A: 'a + Clone, B: 'a>(
1953			func: impl Fn(A, B) -> B + 'a,
1954			initial: B,
1955			fa: Apply!(<Self as Kind!( type Of<'a, T: 'a>: 'a; )>::Of<'a, A>),
1956		) -> B
1957		where
1958			FnBrand: CloneFn + 'a, {
1959			func(fa.0, initial)
1960		}
1961
1962		/// Folds the pair from the left (over first).
1963		///
1964		/// This method performs a left-associative fold of the result (over error).
1965		#[document_signature]
1966		///
1967		#[document_type_parameters(
1968			"The lifetime of the values.",
1969			"The brand of the cloneable function to use.",
1970			"The type of the elements in the structure.",
1971			"The type of the accumulator."
1972		)]
1973		///
1974		#[document_parameters("The folding function.", "The initial value.", "The result to fold.")]
1975		///
1976		#[document_returns("`func(initial, a)` if `fa` is `Err(a)`, otherwise `initial`.")]
1977		///
1978		#[document_examples]
1979		///
1980		/// ```
1981		/// use fp_library::{
1982		/// 	brands::*,
1983		/// 	functions::*,
1984		/// 	types::*,
1985		/// };
1986		///
1987		/// assert_eq!(
1988		/// 	explicit::fold_left::<RcFnBrand, PairSecondAppliedBrand<()>, _, _, _, _>(
1989		/// 		|acc, x| acc + x,
1990		/// 		0,
1991		/// 		Pair(5, ())
1992		/// 	),
1993		/// 	5
1994		/// );
1995		/// ```
1996		fn fold_left<'a, FnBrand, A: 'a + Clone, B: 'a>(
1997			func: impl Fn(B, A) -> B + 'a,
1998			initial: B,
1999			fa: Apply!(<Self as Kind!( type Of<'a, T: 'a>: 'a; )>::Of<'a, A>),
2000		) -> B
2001		where
2002			FnBrand: CloneFn + 'a, {
2003			func(initial, fa.0)
2004		}
2005
2006		/// Maps the value to a monoid and returns it (over first).
2007		///
2008		/// This method maps the element of the result to a monoid and then returns it (over error).
2009		#[document_signature]
2010		///
2011		#[document_type_parameters(
2012			"The lifetime of the values.",
2013			"The brand of the cloneable function to use.",
2014			"The type of the elements in the structure.",
2015			"The type of the monoid."
2016		)]
2017		///
2018		#[document_parameters("The mapping function.", "The result to fold.")]
2019		///
2020		#[document_returns("`func(a)` if `fa` is `Err(a)`, otherwise `M::empty()`.")]
2021		///
2022		#[document_examples]
2023		///
2024		/// ```
2025		/// use fp_library::{
2026		/// 	brands::*,
2027		/// 	functions::*,
2028		/// 	types::*,
2029		/// };
2030		///
2031		/// assert_eq!(
2032		/// 	explicit::fold_map::<RcFnBrand, PairSecondAppliedBrand<()>, _, _, _, _>(
2033		/// 		|x: i32| x.to_string(),
2034		/// 		Pair(5, ())
2035		/// 	),
2036		/// 	"5".to_string()
2037		/// );
2038		/// ```
2039		fn fold_map<'a, FnBrand, A: 'a + Clone, M>(
2040			func: impl Fn(A) -> M + 'a,
2041			fa: Apply!(<Self as Kind!( type Of<'a, T: 'a>: 'a; )>::Of<'a, A>),
2042		) -> M
2043		where
2044			M: Monoid + 'a,
2045			FnBrand: CloneFn + 'a, {
2046			func(fa.0)
2047		}
2048	}
2049
2050	#[document_type_parameters("The type of the second value in the pair.")]
2051	impl<Second: Clone + 'static> Traversable for PairSecondAppliedBrand<Second> {
2052		/// Traverses the pair with an applicative function (over first).
2053		///
2054		/// This method maps the element of the result to a computation, evaluates it, and combines the result into an applicative context (over error).
2055		#[document_signature]
2056		///
2057		#[document_type_parameters(
2058			"The lifetime of the values.",
2059			"The type of the elements in the traversable structure.",
2060			"The type of the elements in the resulting traversable structure.",
2061			"The applicative context."
2062		)]
2063		///
2064		#[document_parameters("The function to apply.", "The result to traverse.")]
2065		///
2066		#[document_returns("The result wrapped in the applicative context.")]
2067		///
2068		#[document_examples]
2069		///
2070		/// ```
2071		/// use fp_library::{
2072		/// 	brands::*,
2073		/// 	functions::*,
2074		/// 	types::*,
2075		/// };
2076		///
2077		/// assert_eq!(
2078		/// 	explicit::traverse::<RcFnBrand, PairSecondAppliedBrand<()>, _, _, OptionBrand, _, _>(
2079		/// 		|x| Some(x * 2),
2080		/// 		Pair(5, ())
2081		/// 	),
2082		/// 	Some(Pair(10, ()))
2083		/// );
2084		/// ```
2085		fn traverse<'a, A: 'a + Clone, B: 'a + Clone, F: Applicative>(
2086			func: impl Fn(A) -> Apply!(<F as Kind!( type Of<'a, T: 'a>: 'a; )>::Of<'a, B>) + 'a,
2087			ta: Apply!(<Self as Kind!( type Of<'a, T: 'a>: 'a; )>::Of<'a, A>),
2088		) -> Apply!(<F as Kind!( type Of<'a, T: 'a>: 'a; )>::Of<'a, Apply!(<Self as Kind!( type Of<'a, T: 'a>: 'a; )>::Of<'a, B>)>)
2089		where
2090			Apply!(<Self as Kind!( type Of<'a, T: 'a>: 'a; )>::Of<'a, B>): Clone, {
2091			let Pair(first, second) = ta;
2092			F::map(move |b| Pair(b, second.clone()), func(first))
2093		}
2094
2095		/// Sequences a pair of applicative (over first).
2096		///
2097		/// This method evaluates the computation inside the result and accumulates the result into an applicative context (over error).
2098		#[document_signature]
2099		///
2100		#[document_type_parameters(
2101			"The lifetime of the values.",
2102			"The type of the elements in the traversable structure.",
2103			"The applicative context."
2104		)]
2105		///
2106		#[document_parameters("The result containing the applicative value.")]
2107		///
2108		#[document_returns("The result wrapped in the applicative context.")]
2109		///
2110		#[document_examples]
2111		///
2112		/// ```
2113		/// use fp_library::{
2114		/// 	brands::*,
2115		/// 	functions::*,
2116		/// 	types::*,
2117		/// };
2118		///
2119		/// assert_eq!(
2120		/// 	sequence::<PairSecondAppliedBrand<()>, _, OptionBrand>(Pair(Some(5), ())),
2121		/// 	Some(Pair(5, ()))
2122		/// );
2123		/// ```
2124		fn sequence<'a, A: 'a + Clone, F: Applicative>(
2125			ta: Apply!(<Self as Kind!( type Of<'a, T: 'a>: 'a; )>::Of<'a, Apply!(<F as Kind!( type Of<'a, T: 'a>: 'a; )>::Of<'a, A>)>)
2126		) -> Apply!(<F as Kind!( type Of<'a, T: 'a>: 'a; )>::Of<'a, Apply!(<Self as Kind!( type Of<'a, T: 'a>: 'a; )>::Of<'a, A>)>)
2127		where
2128			Apply!(<F as Kind!( type Of<'a, T: 'a>: 'a; )>::Of<'a, A>): Clone,
2129			Apply!(<Self as Kind!( type Of<'a, T: 'a>: 'a; )>::Of<'a, A>): Clone, {
2130			let Pair(first, second) = ta;
2131			F::map(move |a| Pair(a, second.clone()), first)
2132		}
2133	}
2134	// -- By-reference trait implementations for PairSecondAppliedBrand --
2135
2136	#[document_type_parameters("The type of the second value in the pair.")]
2137	impl<Second: Clone + 'static> RefFunctor for PairSecondAppliedBrand<Second> {
2138		/// Maps a function over the first value in the pair by reference.
2139		#[document_signature]
2140		#[document_type_parameters("The lifetime.", "The input type.", "The output type.")]
2141		#[document_parameters("The function.", "The pair.")]
2142		#[document_returns("A new pair with the mapped first value.")]
2143		#[document_examples]
2144		///
2145		/// ```
2146		/// use fp_library::{
2147		/// 	brands::*,
2148		/// 	functions::*,
2149		/// 	types::*,
2150		/// };
2151		/// assert_eq!(
2152		/// 	explicit::map::<PairSecondAppliedBrand<_>, _, _, _, _>(|x: &i32| *x * 2, &Pair(5, 1)),
2153		/// 	Pair(10, 1)
2154		/// );
2155		/// ```
2156		fn ref_map<'a, A: 'a, B: 'a>(
2157			func: impl Fn(&A) -> B + 'a,
2158			fa: &Apply!(<Self as Kind!( type Of<'a, T: 'a>: 'a; )>::Of<'a, A>),
2159		) -> Apply!(<Self as Kind!( type Of<'a, T: 'a>: 'a; )>::Of<'a, B>) {
2160			Pair(func(&fa.0), fa.1.clone())
2161		}
2162	}
2163
2164	#[document_type_parameters("The type of the second value in the pair.")]
2165	impl<Second: Clone + 'static> RefFoldable for PairSecondAppliedBrand<Second> {
2166		/// Folds the pair by reference (over first).
2167		#[document_signature]
2168		#[document_type_parameters(
2169			"The lifetime.",
2170			"The brand.",
2171			"The element type.",
2172			"The monoid type."
2173		)]
2174		#[document_parameters("The mapping function.", "The pair.")]
2175		#[document_returns("The monoid value.")]
2176		#[document_examples]
2177		///
2178		/// ```
2179		/// use fp_library::{
2180		/// 	brands::*,
2181		/// 	functions::*,
2182		/// 	types::*,
2183		/// };
2184		/// let result = explicit::fold_map::<RcFnBrand, PairSecondAppliedBrand<()>, _, _, _, _>(
2185		/// 	|x: &i32| x.to_string(),
2186		/// 	&Pair(5, ()),
2187		/// );
2188		/// assert_eq!(result, "5");
2189		/// ```
2190		fn ref_fold_map<'a, FnBrand, A: 'a + Clone, M>(
2191			func: impl Fn(&A) -> M + 'a,
2192			fa: &Apply!(<Self as Kind!( type Of<'a, T: 'a>: 'a; )>::Of<'a, A>),
2193		) -> M
2194		where
2195			FnBrand: LiftFn + 'a,
2196			M: Monoid + 'a, {
2197			func(&fa.0)
2198		}
2199	}
2200
2201	#[document_type_parameters("The type of the second value in the pair.")]
2202	impl<Second: Clone + 'static> RefTraversable for PairSecondAppliedBrand<Second> {
2203		/// Traverses the pair by reference (over first).
2204		#[document_signature]
2205		#[document_type_parameters(
2206			"The lifetime.",
2207			"The brand.",
2208			"The input type.",
2209			"The output type.",
2210			"The applicative."
2211		)]
2212		#[document_parameters("The function.", "The pair.")]
2213		#[document_returns("The traversed result.")]
2214		#[document_examples]
2215		///
2216		/// ```
2217		/// use fp_library::{
2218		/// 	brands::*,
2219		/// 	functions::*,
2220		/// 	types::*,
2221		/// };
2222		/// let result: Option<Pair<String, ()>> =
2223		/// 	ref_traverse::<PairSecondAppliedBrand<()>, RcFnBrand, _, _, OptionBrand>(
2224		/// 		|x: &i32| Some(x.to_string()),
2225		/// 		&Pair(42, ()),
2226		/// 	);
2227		/// assert_eq!(result, Some(Pair("42".to_string(), ())));
2228		/// ```
2229		fn ref_traverse<'a, FnBrand, A: 'a + Clone, B: 'a + Clone, F: Applicative>(
2230			func: impl Fn(&A) -> Apply!(<F as Kind!( type Of<'a, T: 'a>: 'a; )>::Of<'a, B>) + 'a,
2231			ta: &Apply!(<Self as Kind!( type Of<'a, T: 'a>: 'a; )>::Of<'a, A>),
2232		) -> Apply!(<F as Kind!( type Of<'a, T: 'a>: 'a; )>::Of<'a, Apply!(<Self as Kind!( type Of<'a, T: 'a>: 'a; )>::Of<'a, B>)>)
2233		where
2234			FnBrand: LiftFn + 'a,
2235			Apply!(<Self as Kind!( type Of<'a, T: 'a>: 'a; )>::Of<'a, B>): Clone,
2236			Apply!(<F as Kind!( type Of<'a, T: 'a>: 'a; )>::Of<'a, B>): Clone, {
2237			let second = ta.1.clone();
2238			F::map(move |a| Pair(a, second.clone()), func(&ta.0))
2239		}
2240	}
2241
2242	#[document_type_parameters("The type of the second value in the pair.")]
2243	impl<Second: Clone + 'static> RefPointed for PairSecondAppliedBrand<Second>
2244	where
2245		Second: Monoid,
2246	{
2247		/// Creates a pair from a reference by cloning (with empty second).
2248		#[document_signature]
2249		#[document_type_parameters("The lifetime.", "The value type.")]
2250		#[document_parameters("The reference to wrap.")]
2251		#[document_returns("A pair containing a clone of the value and `Monoid::empty()`.")]
2252		#[document_examples]
2253		///
2254		/// ```
2255		/// use fp_library::{
2256		/// 	brands::*,
2257		/// 	functions::*,
2258		/// 	types::*,
2259		/// };
2260		///
2261		/// let x = 42;
2262		/// let result: Pair<i32, String> = ref_pure::<PairSecondAppliedBrand<String>, _>(&x);
2263		/// assert_eq!(result, Pair(42, "".to_string()));
2264		/// ```
2265		fn ref_pure<'a, A: Clone + 'a>(
2266			a: &A
2267		) -> Apply!(<Self as Kind!( type Of<'a, T: 'a>: 'a; )>::Of<'a, A>) {
2268			Pair(a.clone(), Monoid::empty())
2269		}
2270	}
2271
2272	#[document_type_parameters("The type of the second value in the pair.")]
2273	impl<Second: Clone + 'static> RefLift for PairSecondAppliedBrand<Second>
2274	where
2275		Second: Semigroup,
2276	{
2277		/// Combines two pairs with a by-reference binary function (over first).
2278		#[document_signature]
2279		#[document_type_parameters("The lifetime.", "First input.", "Second input.", "Output.")]
2280		#[document_parameters("The binary function.", "The first pair.", "The second pair.")]
2281		#[document_returns("A pair with the function result and combined second values.")]
2282		#[document_examples]
2283		///
2284		/// ```
2285		/// use fp_library::{
2286		/// 	brands::*,
2287		/// 	functions::*,
2288		/// 	types::*,
2289		/// };
2290		///
2291		/// let result = explicit::lift2::<PairSecondAppliedBrand<String>, _, _, _, _, _, _>(
2292		/// 	|a: &i32, b: &i32| *a + *b,
2293		/// 	&Pair(1, "a".to_string()),
2294		/// 	&Pair(2, "b".to_string()),
2295		/// );
2296		/// assert_eq!(result, Pair(3, "ab".to_string()));
2297		/// ```
2298		fn ref_lift2<'a, A: 'a, B: 'a, C: 'a>(
2299			func: impl Fn(&A, &B) -> C + 'a,
2300			fa: &Apply!(<Self as Kind!( type Of<'a, T: 'a>: 'a; )>::Of<'a, A>),
2301			fb: &Apply!(<Self as Kind!( type Of<'a, T: 'a>: 'a; )>::Of<'a, B>),
2302		) -> Apply!(<Self as Kind!( type Of<'a, T: 'a>: 'a; )>::Of<'a, C>) {
2303			Pair(func(&fa.0, &fb.0), Semigroup::append(fa.1.clone(), fb.1.clone()))
2304		}
2305	}
2306
2307	#[document_type_parameters("The type of the second value in the pair.")]
2308	impl<Second: Clone + 'static> RefSemiapplicative for PairSecondAppliedBrand<Second>
2309	where
2310		Second: Semigroup,
2311	{
2312		/// Applies a wrapped by-ref function to a pair value (over first).
2313		#[document_signature]
2314		#[document_type_parameters(
2315			"The lifetime.",
2316			"The function brand.",
2317			"The input type.",
2318			"The output type."
2319		)]
2320		#[document_parameters(
2321			"The pair containing the function.",
2322			"The pair containing the value."
2323		)]
2324		#[document_returns("A pair with the function result and combined second values.")]
2325		#[document_examples]
2326		///
2327		/// ```
2328		/// use fp_library::{
2329		/// 	brands::*,
2330		/// 	functions::*,
2331		/// 	types::*,
2332		/// };
2333		///
2334		/// let f: std::rc::Rc<dyn Fn(&i32) -> i32> = std::rc::Rc::new(|x: &i32| *x * 2);
2335		/// let result = ref_apply::<RcFnBrand, PairSecondAppliedBrand<String>, _, _>(
2336		/// 	&Pair(f, "a".to_string()),
2337		/// 	&Pair(5, "b".to_string()),
2338		/// );
2339		/// assert_eq!(result, Pair(10, "ab".to_string()));
2340		/// ```
2341		fn ref_apply<'a, FnBrand: 'a + CloneFn<Ref>, A: 'a, B: 'a>(
2342			ff: &Apply!(<Self as Kind!( type Of<'a, T: 'a>: 'a; )>::Of<'a, <FnBrand as CloneFn<Ref>>::Of<'a, A, B>>),
2343			fa: &Apply!(<Self as Kind!( type Of<'a, T: 'a>: 'a; )>::Of<'a, A>),
2344		) -> Apply!(<Self as Kind!( type Of<'a, T: 'a>: 'a; )>::Of<'a, B>) {
2345			Pair((*ff.0)(&fa.0), Semigroup::append(ff.1.clone(), fa.1.clone()))
2346		}
2347	}
2348
2349	#[document_type_parameters("The type of the second value in the pair.")]
2350	impl<Second: Clone + 'static> RefSemimonad for PairSecondAppliedBrand<Second>
2351	where
2352		Second: Semigroup,
2353	{
2354		/// Chains pair computations by reference (over first).
2355		#[document_signature]
2356		#[document_type_parameters("The lifetime.", "The input type.", "The output type.")]
2357		#[document_parameters("The input pair.", "The function to apply by reference.")]
2358		#[document_returns("A pair with combined second values.")]
2359		#[document_examples]
2360		///
2361		/// ```
2362		/// use fp_library::{
2363		/// 	brands::*,
2364		/// 	functions::*,
2365		/// 	types::*,
2366		/// };
2367		///
2368		/// let result: Pair<String, String> = explicit::bind::<PairSecondAppliedBrand<String>, _, _, _, _>(
2369		/// 	&Pair(42, "a".to_string()),
2370		/// 	|x: &i32| Pair(x.to_string(), "b".to_string()),
2371		/// );
2372		/// assert_eq!(result, Pair("42".to_string(), "ab".to_string()));
2373		/// ```
2374		fn ref_bind<'a, A: 'a, B: 'a>(
2375			fa: &Apply!(<Self as Kind!( type Of<'a, T: 'a>: 'a; )>::Of<'a, A>),
2376			f: impl Fn(&A) -> Apply!(<Self as Kind!( type Of<'a, T: 'a>: 'a; )>::Of<'a, B>) + 'a,
2377		) -> Apply!(<Self as Kind!( type Of<'a, T: 'a>: 'a; )>::Of<'a, B>) {
2378			let Pair(next_first, next_second) = f(&fa.0);
2379			Pair(next_first, Semigroup::append(fa.1.clone(), next_second))
2380		}
2381	}
2382}
2383pub use inner::*;
2384
2385#[cfg(test)]
2386mod tests {
2387	use {
2388		super::inner::*,
2389		crate::{
2390			brands::*,
2391			classes::{
2392				semiapplicative::apply as explicit_apply,
2393				*,
2394			},
2395			functions::*,
2396		},
2397		quickcheck_macros::quickcheck,
2398	};
2399
2400	// Bifunctor Tests
2401
2402	/// Tests `bimap` on `Pair`.
2403	#[test]
2404	fn test_bimap() {
2405		let x = Pair(1, 5);
2406		assert_eq!(
2407			explicit::bimap::<PairBrand, _, _, _, _, _, _>((|a| a + 1, |b| b * 2), x),
2408			Pair(2, 10)
2409		);
2410	}
2411
2412	// Bifunctor Laws
2413
2414	/// Tests the identity law for Bifunctor.
2415	#[quickcheck]
2416	fn bifunctor_identity(
2417		first: String,
2418		second: i32,
2419	) -> bool {
2420		let x = Pair(first, second);
2421		explicit::bimap::<PairBrand, _, _, _, _, _, _>((identity, identity), x.clone()) == x
2422	}
2423
2424	/// Tests the composition law for Bifunctor.
2425	#[quickcheck]
2426	fn bifunctor_composition(
2427		first: i32,
2428		second: i32,
2429	) -> bool {
2430		let x = Pair(first, second);
2431		let f = |x: i32| x.wrapping_add(1);
2432		let g = |x: i32| x.wrapping_mul(2);
2433		let h = |x: i32| x.wrapping_sub(1);
2434		let i = |x: i32| if x == 0 { 0 } else { x.wrapping_div(2) };
2435
2436		explicit::bimap::<PairBrand, _, _, _, _, _, _>((compose(f, g), compose(h, i)), x)
2437			== explicit::bimap::<PairBrand, _, _, _, _, _, _>(
2438				(f, h),
2439				explicit::bimap::<PairBrand, _, _, _, _, _, _>((g, i), x),
2440			)
2441	}
2442
2443	// Functor Laws
2444
2445	/// Tests the identity law for Functor.
2446	#[quickcheck]
2447	fn functor_identity(
2448		first: String,
2449		second: i32,
2450	) -> bool {
2451		let x = Pair(first, second);
2452		explicit::map::<PairFirstAppliedBrand<String>, _, _, _, _>(identity, x.clone()) == x
2453	}
2454
2455	/// Tests the composition law for Functor.
2456	#[quickcheck]
2457	fn functor_composition(
2458		first: String,
2459		second: i32,
2460	) -> bool {
2461		let x = Pair(first, second);
2462		let f = |x: i32| x.wrapping_add(1);
2463		let g = |x: i32| x.wrapping_mul(2);
2464		explicit::map::<PairFirstAppliedBrand<String>, _, _, _, _>(compose(f, g), x.clone())
2465			== explicit::map::<PairFirstAppliedBrand<String>, _, _, _, _>(
2466				f,
2467				explicit::map::<PairFirstAppliedBrand<String>, _, _, _, _>(g, x),
2468			)
2469	}
2470
2471	// Applicative Laws
2472
2473	/// Tests the identity law for Applicative.
2474	#[quickcheck]
2475	fn applicative_identity(
2476		first: String,
2477		second: i32,
2478	) -> bool {
2479		let v = Pair(first, second);
2480		explicit_apply::<RcFnBrand, PairFirstAppliedBrand<String>, _, _>(
2481			pure::<PairFirstAppliedBrand<String>, _>(<RcFnBrand as LiftFn>::new(identity)),
2482			v.clone(),
2483		) == v
2484	}
2485
2486	/// Tests the homomorphism law for Applicative.
2487	#[quickcheck]
2488	fn applicative_homomorphism(x: i32) -> bool {
2489		let f = |x: i32| x.wrapping_mul(2);
2490		explicit_apply::<RcFnBrand, PairFirstAppliedBrand<String>, _, _>(
2491			pure::<PairFirstAppliedBrand<String>, _>(<RcFnBrand as LiftFn>::new(f)),
2492			pure::<PairFirstAppliedBrand<String>, _>(x),
2493		) == pure::<PairFirstAppliedBrand<String>, _>(f(x))
2494	}
2495
2496	/// Tests the composition law for Applicative.
2497	#[quickcheck]
2498	fn applicative_composition(
2499		w_first: String,
2500		w_second: i32,
2501		u_seed: i32,
2502		v_seed: i32,
2503	) -> bool {
2504		let w = Pair(w_first, w_second);
2505
2506		let u_fn = <RcFnBrand as LiftFn>::new(move |x: i32| x.wrapping_add(u_seed));
2507		let u = pure::<PairFirstAppliedBrand<String>, _>(u_fn);
2508
2509		let v_fn = <RcFnBrand as LiftFn>::new(move |x: i32| x.wrapping_mul(v_seed));
2510		let v = pure::<PairFirstAppliedBrand<String>, _>(v_fn);
2511
2512		// RHS: u <*> (v <*> w)
2513		let vw =
2514			explicit_apply::<RcFnBrand, PairFirstAppliedBrand<String>, _, _>(v.clone(), w.clone());
2515		let rhs = explicit_apply::<RcFnBrand, PairFirstAppliedBrand<String>, _, _>(u.clone(), vw);
2516
2517		// LHS: pure(compose) <*> u <*> v <*> w
2518		let compose_fn = <RcFnBrand as LiftFn>::new(|f: std::rc::Rc<dyn Fn(i32) -> i32>| {
2519			let f = f.clone();
2520			<RcFnBrand as LiftFn>::new(move |g: std::rc::Rc<dyn Fn(i32) -> i32>| {
2521				let f = f.clone();
2522				let g = g.clone();
2523				<RcFnBrand as LiftFn>::new(move |x| f(g(x)))
2524			})
2525		});
2526
2527		let pure_compose = pure::<PairFirstAppliedBrand<String>, _>(compose_fn);
2528		let u_applied =
2529			explicit_apply::<RcFnBrand, PairFirstAppliedBrand<String>, _, _>(pure_compose, u);
2530		let uv = explicit_apply::<RcFnBrand, PairFirstAppliedBrand<String>, _, _>(u_applied, v);
2531		let lhs = explicit_apply::<RcFnBrand, PairFirstAppliedBrand<String>, _, _>(uv, w);
2532
2533		lhs == rhs
2534	}
2535
2536	/// Tests the interchange law for Applicative.
2537	#[quickcheck]
2538	fn applicative_interchange(
2539		y: i32,
2540		u_seed: i32,
2541	) -> bool {
2542		// u <*> pure y = pure ($ y) <*> u
2543		let f = move |x: i32| x.wrapping_mul(u_seed);
2544		let u = pure::<PairFirstAppliedBrand<String>, _>(<RcFnBrand as LiftFn>::new(f));
2545
2546		let lhs = explicit_apply::<RcFnBrand, PairFirstAppliedBrand<String>, _, _>(
2547			u.clone(),
2548			pure::<PairFirstAppliedBrand<String>, _>(y),
2549		);
2550
2551		let rhs_fn = <RcFnBrand as LiftFn>::new(move |f: std::rc::Rc<dyn Fn(i32) -> i32>| f(y));
2552		let rhs = explicit_apply::<RcFnBrand, PairFirstAppliedBrand<String>, _, _>(
2553			pure::<PairFirstAppliedBrand<String>, _>(rhs_fn),
2554			u,
2555		);
2556
2557		lhs == rhs
2558	}
2559
2560	// Monad Laws
2561
2562	/// Tests the left identity law for Monad.
2563	#[quickcheck]
2564	fn monad_left_identity(a: i32) -> bool {
2565		let f = |x: i32| Pair("f".to_string(), x.wrapping_mul(2));
2566		explicit::bind::<PairFirstAppliedBrand<String>, _, _, _, _>(
2567			pure::<PairFirstAppliedBrand<String>, _>(a),
2568			f,
2569		) == f(a)
2570	}
2571
2572	/// Tests the right identity law for Monad.
2573	#[quickcheck]
2574	fn monad_right_identity(
2575		first: String,
2576		second: i32,
2577	) -> bool {
2578		let m = Pair(first, second);
2579		explicit::bind::<PairFirstAppliedBrand<String>, _, _, _, _>(
2580			m.clone(),
2581			pure::<PairFirstAppliedBrand<String>, _>,
2582		) == m
2583	}
2584
2585	/// Tests the associativity law for Monad.
2586	#[quickcheck]
2587	fn monad_associativity(
2588		first: String,
2589		second: i32,
2590	) -> bool {
2591		let m = Pair(first, second);
2592		let f = |x: i32| Pair("f".to_string(), x.wrapping_mul(2));
2593		let g = |x: i32| Pair("g".to_string(), x.wrapping_add(1));
2594		explicit::bind::<PairFirstAppliedBrand<String>, _, _, _, _>(
2595			explicit::bind::<PairFirstAppliedBrand<String>, _, _, _, _>(m.clone(), f),
2596			g,
2597		) == explicit::bind::<PairFirstAppliedBrand<String>, _, _, _, _>(m, |x| {
2598			explicit::bind::<PairFirstAppliedBrand<String>, _, _, _, _>(f(x), g)
2599		})
2600	}
2601
2602	// MonadRec tests for PairFirstAppliedBrand
2603
2604	/// Tests the MonadRec identity law: `tail_rec_m(|a| pure(Done(a)), x) == pure(x)`.
2605	#[quickcheck]
2606	fn monad_rec_first_applied_identity(x: i32) -> bool {
2607		use {
2608			crate::classes::monad_rec::tail_rec_m,
2609			core::ops::ControlFlow,
2610		};
2611		tail_rec_m::<PairFirstAppliedBrand<String>, _, _>(
2612			|a| Pair(String::new(), ControlFlow::Break(a)),
2613			x,
2614		) == Pair(String::new(), x)
2615	}
2616
2617	/// Tests a recursive computation that accumulates the first value.
2618	#[test]
2619	fn monad_rec_first_applied_accumulation() {
2620		use {
2621			crate::classes::monad_rec::tail_rec_m,
2622			core::ops::ControlFlow,
2623		};
2624		let result = tail_rec_m::<PairFirstAppliedBrand<String>, _, _>(
2625			|n: i32| {
2626				if n < 3 {
2627					Pair(format!("{n},"), ControlFlow::Continue(n + 1))
2628				} else {
2629					Pair(format!("{n}"), ControlFlow::Break(n))
2630				}
2631			},
2632			0,
2633		);
2634		assert_eq!(result, Pair("0,1,2,3".to_string(), 3));
2635	}
2636
2637	/// Tests stack safety of MonadRec for PairFirstAppliedBrand.
2638	#[test]
2639	fn monad_rec_first_applied_stack_safety() {
2640		use {
2641			crate::classes::monad_rec::tail_rec_m,
2642			core::ops::ControlFlow,
2643		};
2644		let iterations: i64 = 200_000;
2645		let result = tail_rec_m::<PairFirstAppliedBrand<Vec<()>>, _, _>(
2646			|acc| {
2647				if acc < iterations {
2648					Pair(vec![], ControlFlow::Continue(acc + 1))
2649				} else {
2650					Pair(vec![], ControlFlow::Break(acc))
2651				}
2652			},
2653			0i64,
2654		);
2655		assert_eq!(result, Pair(vec![], iterations));
2656	}
2657
2658	// MonadRec tests for PairSecondAppliedBrand
2659
2660	/// Tests the MonadRec identity law: `tail_rec_m(|a| pure(Done(a)), x) == pure(x)`.
2661	#[quickcheck]
2662	fn monad_rec_second_applied_identity(x: i32) -> bool {
2663		use {
2664			crate::classes::monad_rec::tail_rec_m,
2665			core::ops::ControlFlow,
2666		};
2667		tail_rec_m::<PairSecondAppliedBrand<String>, _, _>(
2668			|a| Pair(ControlFlow::Break(a), String::new()),
2669			x,
2670		) == Pair(x, String::new())
2671	}
2672
2673	/// Tests a recursive computation that accumulates the second value.
2674	#[test]
2675	fn monad_rec_second_applied_accumulation() {
2676		use {
2677			crate::classes::monad_rec::tail_rec_m,
2678			core::ops::ControlFlow,
2679		};
2680		let result = tail_rec_m::<PairSecondAppliedBrand<String>, _, _>(
2681			|n: i32| {
2682				if n < 3 {
2683					Pair(ControlFlow::Continue(n + 1), format!("{n},"))
2684				} else {
2685					Pair(ControlFlow::Break(n), format!("{n}"))
2686				}
2687			},
2688			0,
2689		);
2690		assert_eq!(result, Pair(3, "0,1,2,3".to_string()));
2691	}
2692
2693	/// Tests stack safety of MonadRec for PairSecondAppliedBrand.
2694	#[test]
2695	fn monad_rec_second_applied_stack_safety() {
2696		use {
2697			crate::classes::monad_rec::tail_rec_m,
2698			core::ops::ControlFlow,
2699		};
2700		let iterations: i64 = 200_000;
2701		let result = tail_rec_m::<PairSecondAppliedBrand<Vec<()>>, _, _>(
2702			|acc| {
2703				if acc < iterations {
2704					Pair(ControlFlow::Continue(acc + 1), vec![])
2705				} else {
2706					Pair(ControlFlow::Break(acc), vec![])
2707				}
2708			},
2709			0i64,
2710		);
2711		assert_eq!(result, Pair(iterations, vec![]));
2712	}
2713
2714	// RefBifunctor Laws
2715
2716	/// RefBifunctor identity
2717	#[quickcheck]
2718	fn ref_bifunctor_identity(
2719		a: i32,
2720		b: i32,
2721	) -> bool {
2722		let p = Pair(a, b);
2723		explicit::bimap::<PairBrand, _, _, _, _, _, _>((|x: &i32| *x, |x: &i32| *x), &p) == p
2724	}
2725
2726	/// RefBifunctor composition
2727	#[quickcheck]
2728	fn ref_bifunctor_composition(
2729		a: i32,
2730		b: i32,
2731	) -> bool {
2732		let p = Pair(a, b);
2733		let f1 = |x: &i32| x.wrapping_add(1);
2734		let f2 = |x: &i32| x.wrapping_mul(2);
2735		let g1 = |x: &i32| x.wrapping_add(10);
2736		let g2 = |x: &i32| x.wrapping_mul(3);
2737		explicit::bimap::<PairBrand, _, _, _, _, _, _>(
2738			(|x: &i32| f2(&f1(x)), |x: &i32| g2(&g1(x))),
2739			&p,
2740		) == explicit::bimap::<PairBrand, _, _, _, _, _, _>(
2741			(f2, g2),
2742			&explicit::bimap::<PairBrand, _, _, _, _, _, _>((f1, g1), &p),
2743		)
2744	}
2745
2746	// RefBifoldable Laws
2747
2748	/// RefBifoldable fold_map correctness
2749	#[quickcheck]
2750	fn ref_bifoldable_fold_map(
2751		a: i32,
2752		b: i32,
2753	) -> bool {
2754		let p = Pair(a, b);
2755		let result = explicit::bi_fold_map::<RcFnBrand, PairBrand, _, _, _, _, _>(
2756			(|x: &i32| x.to_string(), |x: &i32| x.to_string()),
2757			&p,
2758		);
2759		result == format!("{}{}", a, b)
2760	}
2761
2762	// RefBitraversable Laws
2763
2764	/// RefBitraversable consistency
2765	#[quickcheck]
2766	fn ref_bitraversable_consistency(
2767		a: i32,
2768		b: i32,
2769	) -> bool {
2770		let p = Pair(a, b);
2771		let f = |x: &i32| Some(x.wrapping_add(1));
2772		let g = |x: &i32| Some(x.wrapping_mul(2));
2773		let traversed = explicit::bi_traverse::<RcFnBrand, PairBrand, _, _, _, _, OptionBrand, _, _>(
2774			(f, g),
2775			&p,
2776		);
2777		let mapped_then_sequenced =
2778			ref_bi_sequence::<PairBrand, RcFnBrand, _, _, OptionBrand>(&explicit::bimap::<
2779				PairBrand,
2780				_,
2781				_,
2782				_,
2783				_,
2784				_,
2785				_,
2786			>((f, g), &p));
2787		traversed == mapped_then_sequenced
2788	}
2789}