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, 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		#[no_inferable_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		/// 	functions::*,
992		/// 	types::*,
993		/// };
994		///
995		/// let f = Pair("a".to_string(), lift_fn_new::<RcFnBrand, _, _>(|x: i32| x * 2));
996		/// assert_eq!(
997		/// 	apply::<RcFnBrand, PairFirstAppliedBrand<String>, _, _>(f, Pair("b".to_string(), 5)),
998		/// 	Pair("ab".to_string(), 10)
999		/// );
1000		/// ```
1001		fn apply<'a, FnBrand: 'a + CloneFn, A: 'a + Clone, B: 'a>(
1002			ff: Apply!(<Self as Kind!( type Of<'a, T: 'a>: 'a; )>::Of<'a, <FnBrand as CloneFn>::Of<'a, A, B>>),
1003			fa: Apply!(<Self as Kind!( type Of<'a, T: 'a>: 'a; )>::Of<'a, A>),
1004		) -> Apply!(<Self as Kind!( type Of<'a, T: 'a>: 'a; )>::Of<'a, B>) {
1005			Pair(Semigroup::append(ff.0, fa.0), ff.1(fa.1))
1006		}
1007	}
1008
1009	#[document_type_parameters("The type of the first value in the pair.")]
1010	impl<First: Clone + 'static> Semimonad for PairFirstAppliedBrand<First>
1011	where
1012		First: Semigroup,
1013	{
1014		/// Chains pair computations (over second).
1015		///
1016		/// 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.
1017		#[document_signature]
1018		///
1019		#[document_type_parameters(
1020			"The lifetime of the values.",
1021			"The type of the result of the first computation.",
1022			"The type of the result of the second computation."
1023		)]
1024		///
1025		#[document_parameters("The first pair.", "The function to apply to the second value.")]
1026		///
1027		#[document_returns("A new pair where the first values are combined.")]
1028		///
1029		#[document_examples]
1030		///
1031		/// ```
1032		/// use fp_library::{
1033		/// 	brands::*,
1034		/// 	functions::*,
1035		/// 	types::*,
1036		/// };
1037		///
1038		/// assert_eq!(
1039		/// 	explicit::bind::<PairFirstAppliedBrand<String>, _, _, _, _>(
1040		/// 		Pair("a".to_string(), 5),
1041		/// 		|x| { Pair("b".to_string(), x * 2) }
1042		/// 	),
1043		/// 	Pair("ab".to_string(), 10)
1044		/// );
1045		/// ```
1046		fn bind<'a, A: 'a, B: 'a>(
1047			ma: Apply!(<Self as Kind!( type Of<'a, T: 'a>: 'a; )>::Of<'a, A>),
1048			func: impl Fn(A) -> Apply!(<Self as Kind!( type Of<'a, T: 'a>: 'a; )>::Of<'a, B>) + 'a,
1049		) -> Apply!(<Self as Kind!( type Of<'a, T: 'a>: 'a; )>::Of<'a, B>) {
1050			ma.bind(func)
1051		}
1052	}
1053
1054	/// [`MonadRec`] implementation for [`PairFirstAppliedBrand`].
1055	#[document_type_parameters("The type of the first value in the pair.")]
1056	impl<First: Clone + 'static> MonadRec for PairFirstAppliedBrand<First>
1057	where
1058		First: Monoid,
1059	{
1060		/// Performs tail-recursive monadic computation over the second value, accumulating the first.
1061		///
1062		/// Iteratively applies the step function. Each iteration produces a pair
1063		/// whose first value is combined with the running accumulator via
1064		/// [`Semigroup::append`]. If the step returns `ControlFlow::Continue(a)`, the loop
1065		/// continues with the new state. If it returns `ControlFlow::Break(b)`, the
1066		/// computation completes with the accumulated first value and `b`.
1067		#[document_signature]
1068		///
1069		#[document_type_parameters(
1070			"The lifetime of the computation.",
1071			"The type of the initial value and loop state.",
1072			"The type of the result."
1073		)]
1074		///
1075		#[document_parameters("The step function.", "The initial value.")]
1076		///
1077		#[document_returns("A pair with the accumulated first value and the final result.")]
1078		///
1079		#[document_examples]
1080		///
1081		/// ```
1082		/// use {
1083		/// 	core::ops::ControlFlow,
1084		/// 	fp_library::{
1085		/// 		brands::*,
1086		/// 		functions::*,
1087		/// 		types::*,
1088		/// 	},
1089		/// };
1090		///
1091		/// let result = tail_rec_m::<PairFirstAppliedBrand<String>, _, _>(
1092		/// 	|n| {
1093		/// 		if n < 3 {
1094		/// 			Pair(format!("{n},"), ControlFlow::Continue(n + 1))
1095		/// 		} else {
1096		/// 			Pair(format!("{n}"), ControlFlow::Break(n))
1097		/// 		}
1098		/// 	},
1099		/// 	0,
1100		/// );
1101		/// assert_eq!(result, Pair("0,1,2,3".to_string(), 3));
1102		/// ```
1103		fn tail_rec_m<'a, A: 'a, B: 'a>(
1104			func: impl Fn(
1105				A,
1106			)
1107				-> Apply!(<Self as Kind!( type Of<'a, T: 'a>: 'a; )>::Of<'a, ControlFlow<B, A>>)
1108			+ 'a,
1109			initial: A,
1110		) -> Apply!(<Self as Kind!( type Of<'a, T: 'a>: 'a; )>::Of<'a, B>) {
1111			let mut acc: First = Monoid::empty();
1112			let mut current = initial;
1113			loop {
1114				let Pair(first, step) = func(current);
1115				acc = Semigroup::append(acc, first);
1116				match step {
1117					ControlFlow::Continue(next) => current = next,
1118					ControlFlow::Break(b) => return Pair(acc, b),
1119				}
1120			}
1121		}
1122	}
1123
1124	#[document_type_parameters("The type of the first value in the pair.")]
1125	impl<First: 'static> Foldable for PairFirstAppliedBrand<First> {
1126		/// Folds the pair from the right (over second).
1127		///
1128		/// This method performs a right-associative fold of the pair (over second).
1129		#[document_signature]
1130		///
1131		#[document_type_parameters(
1132			"The lifetime of the values.",
1133			"The brand of the cloneable function to use.",
1134			"The type of the elements in the structure.",
1135			"The type of the accumulator."
1136		)]
1137		///
1138		#[document_parameters("The folding function.", "The initial value.", "The pair to fold.")]
1139		///
1140		#[document_returns("`func(a, initial)`.")]
1141		///
1142		#[document_examples]
1143		///
1144		/// ```
1145		/// use fp_library::{
1146		/// 	brands::*,
1147		/// 	functions::*,
1148		/// 	types::*,
1149		/// };
1150		///
1151		/// assert_eq!(
1152		/// 	explicit::fold_right::<RcFnBrand, PairFirstAppliedBrand<()>, _, _, _, _>(
1153		/// 		|x, acc| x + acc,
1154		/// 		0,
1155		/// 		Pair((), 5)
1156		/// 	),
1157		/// 	5
1158		/// );
1159		/// ```
1160		fn fold_right<'a, FnBrand, A: 'a + Clone, B: 'a>(
1161			func: impl Fn(A, B) -> B + 'a,
1162			initial: B,
1163			fa: Apply!(<Self as Kind!( type Of<'a, T: 'a>: 'a; )>::Of<'a, A>),
1164		) -> B
1165		where
1166			FnBrand: CloneFn + 'a, {
1167			func(fa.1, initial)
1168		}
1169
1170		/// Folds the pair from the left (over second).
1171		///
1172		/// This method performs a left-associative fold of the pair (over second).
1173		#[document_signature]
1174		///
1175		#[document_type_parameters(
1176			"The lifetime of the values.",
1177			"The brand of the cloneable function to use.",
1178			"The type of the elements in the structure.",
1179			"The type of the accumulator."
1180		)]
1181		///
1182		#[document_parameters(
1183			"The function to apply to the accumulator and each element.",
1184			"The initial value of the accumulator.",
1185			"The identity to fold."
1186		)]
1187		///
1188		#[document_returns("`func(initial, a)`.")]
1189		#[document_examples]
1190		///
1191		/// ```
1192		/// use fp_library::{
1193		/// 	brands::*,
1194		/// 	functions::*,
1195		/// 	types::*,
1196		/// };
1197		///
1198		/// assert_eq!(
1199		/// 	explicit::fold_left::<RcFnBrand, PairFirstAppliedBrand<()>, _, _, _, _>(
1200		/// 		|acc, x| acc + x,
1201		/// 		0,
1202		/// 		Pair((), 5)
1203		/// 	),
1204		/// 	5
1205		/// );
1206		/// ```
1207		fn fold_left<'a, FnBrand, A: 'a + Clone, B: 'a>(
1208			func: impl Fn(B, A) -> B + 'a,
1209			initial: B,
1210			fa: Apply!(<Self as Kind!( type Of<'a, T: 'a>: 'a; )>::Of<'a, A>),
1211		) -> B
1212		where
1213			FnBrand: CloneFn + 'a, {
1214			func(initial, fa.1)
1215		}
1216
1217		/// Maps the value to a monoid and returns it (over second).
1218		///
1219		/// This method maps the element of the pair to a monoid and then returns it (over second).
1220		#[document_signature]
1221		///
1222		#[document_type_parameters(
1223			"The lifetime of the values.",
1224			"The brand of the cloneable function to use.",
1225			"The type of the elements in the structure.",
1226			"The type of the monoid."
1227		)]
1228		///
1229		#[document_parameters("The mapping function.", "The pair to fold.")]
1230		///
1231		#[document_returns("`func(a)`.")]
1232		///
1233		#[document_examples]
1234		///
1235		/// ```
1236		/// use fp_library::{
1237		/// 	brands::*,
1238		/// 	functions::*,
1239		/// 	types::*,
1240		/// };
1241		///
1242		/// assert_eq!(
1243		/// 	explicit::fold_map::<RcFnBrand, PairFirstAppliedBrand<()>, _, _, _, _>(
1244		/// 		|x: i32| x.to_string(),
1245		/// 		Pair((), 5)
1246		/// 	),
1247		/// 	"5".to_string()
1248		/// );
1249		/// ```
1250		fn fold_map<'a, FnBrand, A: 'a + Clone, M>(
1251			func: impl Fn(A) -> M + 'a,
1252			fa: Apply!(<Self as Kind!( type Of<'a, T: 'a>: 'a; )>::Of<'a, A>),
1253		) -> M
1254		where
1255			M: Monoid + 'a,
1256			FnBrand: CloneFn + 'a, {
1257			func(fa.1)
1258		}
1259	}
1260
1261	#[document_type_parameters("The type of the first value in the pair.")]
1262	impl<First: Clone + 'static> Traversable for PairFirstAppliedBrand<First> {
1263		/// Traverses the pair with an applicative function (over second).
1264		///
1265		/// This method maps the element of the pair to a computation, evaluates it, and combines the result into an applicative context (over second).
1266		#[document_signature]
1267		///
1268		#[document_type_parameters(
1269			"The lifetime of the values.",
1270			"The type of the elements in the traversable structure.",
1271			"The type of the elements in the resulting traversable structure.",
1272			"The applicative context."
1273		)]
1274		///
1275		#[document_parameters(
1276			"The function to apply to each element, returning a value in an applicative context.",
1277			"The pair to traverse."
1278		)]
1279		///
1280		#[document_returns("The pair wrapped in the applicative context.")]
1281		#[document_examples]
1282		///
1283		/// ```
1284		/// use fp_library::{
1285		/// 	brands::*,
1286		/// 	functions::*,
1287		/// 	types::*,
1288		/// };
1289		///
1290		/// assert_eq!(
1291		/// 	explicit::traverse::<RcFnBrand, PairFirstAppliedBrand<()>, _, _, OptionBrand, _, _>(
1292		/// 		|x| Some(x * 2),
1293		/// 		Pair((), 5)
1294		/// 	),
1295		/// 	Some(Pair((), 10))
1296		/// );
1297		/// ```
1298		fn traverse<'a, A: 'a + Clone, B: 'a + Clone, F: Applicative>(
1299			func: impl Fn(A) -> Apply!(<F as Kind!( type Of<'a, T: 'a>: 'a; )>::Of<'a, B>) + 'a,
1300			ta: Apply!(<Self as Kind!( type Of<'a, T: 'a>: 'a; )>::Of<'a, A>),
1301		) -> 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>)>)
1302		where
1303			Apply!(<Self as Kind!( type Of<'a, T: 'a>: 'a; )>::Of<'a, B>): Clone, {
1304			let Pair(first, second) = ta;
1305			F::map(move |b| Pair(first.clone(), b), func(second))
1306		}
1307
1308		/// Sequences a pair of applicative (over second).
1309		///
1310		/// This method evaluates the computation inside the pair and accumulates the result into an applicative context (over second).
1311		#[document_signature]
1312		///
1313		#[document_type_parameters(
1314			"The lifetime of the values.",
1315			"The type of the elements in the traversable structure.",
1316			"The applicative context."
1317		)]
1318		///
1319		#[document_parameters("The pair containing the applicative value.")]
1320		///
1321		#[document_returns("The pair wrapped in the applicative context.")]
1322		///
1323		#[document_examples]
1324		///
1325		/// ```
1326		/// use fp_library::{
1327		/// 	brands::*,
1328		/// 	functions::*,
1329		/// 	types::*,
1330		/// };
1331		///
1332		/// assert_eq!(
1333		/// 	sequence::<PairFirstAppliedBrand<()>, _, OptionBrand>(Pair((), Some(5))),
1334		/// 	Some(Pair((), 5))
1335		/// );
1336		/// ```
1337		fn sequence<'a, A: 'a + Clone, F: Applicative>(
1338			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>)>)
1339		) -> 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>)>)
1340		where
1341			Apply!(<F as Kind!( type Of<'a, T: 'a>: 'a; )>::Of<'a, A>): Clone,
1342			Apply!(<Self as Kind!( type Of<'a, T: 'a>: 'a; )>::Of<'a, A>): Clone, {
1343			let Pair(first, second) = ta;
1344			F::map(move |a| Pair(first.clone(), a), second)
1345		}
1346	}
1347
1348	// -- By-reference trait implementations for PairFirstAppliedBrand --
1349
1350	#[document_type_parameters("The type of the first value in the pair.")]
1351	impl<First: Clone + 'static> RefFunctor for PairFirstAppliedBrand<First> {
1352		/// Maps a function over the second value in the pair by reference.
1353		#[document_signature]
1354		#[document_type_parameters("The lifetime.", "The input type.", "The output type.")]
1355		#[document_parameters("The function.", "The pair.")]
1356		#[document_returns("A new pair with the mapped second value.")]
1357		#[document_examples]
1358		///
1359		/// ```
1360		/// use fp_library::{
1361		/// 	brands::*,
1362		/// 	functions::*,
1363		/// 	types::*,
1364		/// };
1365		/// assert_eq!(
1366		/// 	explicit::map::<PairFirstAppliedBrand<_>, _, _, _, _>(|x: &i32| *x * 2, &Pair(1, 5)),
1367		/// 	Pair(1, 10)
1368		/// );
1369		/// ```
1370		fn ref_map<'a, A: 'a, B: 'a>(
1371			func: impl Fn(&A) -> B + 'a,
1372			fa: &Apply!(<Self as Kind!( type Of<'a, T: 'a>: 'a; )>::Of<'a, A>),
1373		) -> Apply!(<Self as Kind!( type Of<'a, T: 'a>: 'a; )>::Of<'a, B>) {
1374			Pair(fa.0.clone(), func(&fa.1))
1375		}
1376	}
1377
1378	#[document_type_parameters("The type of the first value in the pair.")]
1379	impl<First: Clone + 'static> RefFoldable for PairFirstAppliedBrand<First> {
1380		/// Folds the pair by reference (over second).
1381		#[document_signature]
1382		#[document_type_parameters(
1383			"The lifetime.",
1384			"The brand.",
1385			"The element type.",
1386			"The monoid type."
1387		)]
1388		#[document_parameters("The mapping function.", "The pair.")]
1389		#[document_returns("The monoid value.")]
1390		#[document_examples]
1391		///
1392		/// ```
1393		/// use fp_library::{
1394		/// 	brands::*,
1395		/// 	functions::*,
1396		/// 	types::*,
1397		/// };
1398		/// let result = explicit::fold_map::<RcFnBrand, PairFirstAppliedBrand<()>, _, _, _, _>(
1399		/// 	|x: &i32| x.to_string(),
1400		/// 	&Pair((), 5),
1401		/// );
1402		/// assert_eq!(result, "5");
1403		/// ```
1404		fn ref_fold_map<'a, FnBrand, A: 'a + Clone, M>(
1405			func: impl Fn(&A) -> M + 'a,
1406			fa: &Apply!(<Self as Kind!( type Of<'a, T: 'a>: 'a; )>::Of<'a, A>),
1407		) -> M
1408		where
1409			FnBrand: LiftFn + 'a,
1410			M: Monoid + 'a, {
1411			func(&fa.1)
1412		}
1413	}
1414
1415	#[document_type_parameters("The type of the first value in the pair.")]
1416	impl<First: Clone + 'static> RefTraversable for PairFirstAppliedBrand<First> {
1417		/// Traverses the pair by reference (over second).
1418		#[document_signature]
1419		#[document_type_parameters(
1420			"The lifetime.",
1421			"The brand.",
1422			"The input type.",
1423			"The output type.",
1424			"The applicative."
1425		)]
1426		#[document_parameters("The function.", "The pair.")]
1427		#[document_returns("The traversed result.")]
1428		#[document_examples]
1429		///
1430		/// ```
1431		/// use fp_library::{
1432		/// 	brands::*,
1433		/// 	functions::*,
1434		/// 	types::*,
1435		/// };
1436		/// let result: Option<Pair<(), String>> =
1437		/// 	ref_traverse::<PairFirstAppliedBrand<()>, RcFnBrand, _, _, OptionBrand>(
1438		/// 		|x: &i32| Some(x.to_string()),
1439		/// 		&Pair((), 42),
1440		/// 	);
1441		/// assert_eq!(result, Some(Pair((), "42".to_string())));
1442		/// ```
1443		fn ref_traverse<'a, FnBrand, A: 'a + Clone, B: 'a + Clone, F: Applicative>(
1444			func: impl Fn(&A) -> Apply!(<F as Kind!( type Of<'a, T: 'a>: 'a; )>::Of<'a, B>) + 'a,
1445			ta: &Apply!(<Self as Kind!( type Of<'a, T: 'a>: 'a; )>::Of<'a, A>),
1446		) -> 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>)>)
1447		where
1448			FnBrand: LiftFn + 'a,
1449			Apply!(<Self as Kind!( type Of<'a, T: 'a>: 'a; )>::Of<'a, B>): Clone,
1450			Apply!(<F as Kind!( type Of<'a, T: 'a>: 'a; )>::Of<'a, B>): Clone, {
1451			let first = ta.0.clone();
1452			F::map(move |b| Pair(first.clone(), b), func(&ta.1))
1453		}
1454	}
1455
1456	#[document_type_parameters("The type of the first value in the pair.")]
1457	impl<First: Clone + 'static> RefPointed for PairFirstAppliedBrand<First>
1458	where
1459		First: Monoid,
1460	{
1461		/// Creates a pair from a reference by cloning (with empty first).
1462		#[document_signature]
1463		#[document_type_parameters("The lifetime.", "The value type.")]
1464		#[document_parameters("The reference to wrap.")]
1465		#[document_returns("A pair containing `Monoid::empty()` and a clone of the value.")]
1466		#[document_examples]
1467		///
1468		/// ```
1469		/// use fp_library::{
1470		/// 	brands::*,
1471		/// 	functions::*,
1472		/// 	types::*,
1473		/// };
1474		///
1475		/// let x = 42;
1476		/// let result: Pair<String, i32> = ref_pure::<PairFirstAppliedBrand<String>, _>(&x);
1477		/// assert_eq!(result, Pair("".to_string(), 42));
1478		/// ```
1479		fn ref_pure<'a, A: Clone + 'a>(
1480			a: &A
1481		) -> Apply!(<Self as Kind!( type Of<'a, T: 'a>: 'a; )>::Of<'a, A>) {
1482			Pair(Monoid::empty(), a.clone())
1483		}
1484	}
1485
1486	#[document_type_parameters("The type of the first value in the pair.")]
1487	impl<First: Clone + 'static> RefLift for PairFirstAppliedBrand<First>
1488	where
1489		First: Semigroup,
1490	{
1491		/// Combines two pairs with a by-reference binary function (over second).
1492		#[document_signature]
1493		#[document_type_parameters("The lifetime.", "First input.", "Second input.", "Output.")]
1494		#[document_parameters("The binary function.", "The first pair.", "The second pair.")]
1495		#[document_returns("A pair with combined first values and the function result.")]
1496		#[document_examples]
1497		///
1498		/// ```
1499		/// use fp_library::{
1500		/// 	brands::*,
1501		/// 	functions::*,
1502		/// 	types::*,
1503		/// };
1504		///
1505		/// let result = explicit::lift2::<PairFirstAppliedBrand<String>, _, _, _, _, _, _>(
1506		/// 	|a: &i32, b: &i32| *a + *b,
1507		/// 	&Pair("a".to_string(), 1),
1508		/// 	&Pair("b".to_string(), 2),
1509		/// );
1510		/// assert_eq!(result, Pair("ab".to_string(), 3));
1511		/// ```
1512		fn ref_lift2<'a, A: 'a, B: 'a, C: 'a>(
1513			func: impl Fn(&A, &B) -> C + 'a,
1514			fa: &Apply!(<Self as Kind!( type Of<'a, T: 'a>: 'a; )>::Of<'a, A>),
1515			fb: &Apply!(<Self as Kind!( type Of<'a, T: 'a>: 'a; )>::Of<'a, B>),
1516		) -> Apply!(<Self as Kind!( type Of<'a, T: 'a>: 'a; )>::Of<'a, C>) {
1517			Pair(Semigroup::append(fa.0.clone(), fb.0.clone()), func(&fa.1, &fb.1))
1518		}
1519	}
1520
1521	#[document_type_parameters("The type of the first value in the pair.")]
1522	impl<First: Clone + 'static> RefSemiapplicative for PairFirstAppliedBrand<First>
1523	where
1524		First: Semigroup,
1525	{
1526		/// Applies a wrapped by-ref function to a pair value (over second).
1527		#[document_signature]
1528		#[document_type_parameters(
1529			"The lifetime.",
1530			"The function brand.",
1531			"The input type.",
1532			"The output type."
1533		)]
1534		#[document_parameters(
1535			"The pair containing the function.",
1536			"The pair containing the value."
1537		)]
1538		#[document_returns("A pair with combined first values and the function result.")]
1539		#[document_examples]
1540		///
1541		/// ```
1542		/// use fp_library::{
1543		/// 	brands::*,
1544		/// 	functions::*,
1545		/// 	types::*,
1546		/// };
1547		///
1548		/// let f: std::rc::Rc<dyn Fn(&i32) -> i32> = std::rc::Rc::new(|x: &i32| *x * 2);
1549		/// let result = ref_apply::<RcFnBrand, PairFirstAppliedBrand<String>, _, _>(
1550		/// 	&Pair("a".to_string(), f),
1551		/// 	&Pair("b".to_string(), 5),
1552		/// );
1553		/// assert_eq!(result, Pair("ab".to_string(), 10));
1554		/// ```
1555		fn ref_apply<'a, FnBrand: 'a + CloneFn<Ref>, A: 'a, B: 'a>(
1556			ff: &Apply!(<Self as Kind!( type Of<'a, T: 'a>: 'a; )>::Of<'a, <FnBrand as CloneFn<Ref>>::Of<'a, A, B>>),
1557			fa: &Apply!(<Self as Kind!( type Of<'a, T: 'a>: 'a; )>::Of<'a, A>),
1558		) -> Apply!(<Self as Kind!( type Of<'a, T: 'a>: 'a; )>::Of<'a, B>) {
1559			Pair(Semigroup::append(ff.0.clone(), fa.0.clone()), (*ff.1)(&fa.1))
1560		}
1561	}
1562
1563	#[document_type_parameters("The type of the first value in the pair.")]
1564	impl<First: Clone + 'static> RefSemimonad for PairFirstAppliedBrand<First>
1565	where
1566		First: Semigroup,
1567	{
1568		/// Chains pair computations by reference (over second).
1569		#[document_signature]
1570		#[document_type_parameters("The lifetime.", "The input type.", "The output type.")]
1571		#[document_parameters("The input pair.", "The function to apply by reference.")]
1572		#[document_returns("A pair with combined first values.")]
1573		#[document_examples]
1574		///
1575		/// ```
1576		/// use fp_library::{
1577		/// 	brands::*,
1578		/// 	functions::*,
1579		/// 	types::*,
1580		/// };
1581		///
1582		/// let result: Pair<String, String> = explicit::bind::<PairFirstAppliedBrand<String>, _, _, _, _>(
1583		/// 	&Pair("a".to_string(), 42),
1584		/// 	|x: &i32| Pair("b".to_string(), x.to_string()),
1585		/// );
1586		/// assert_eq!(result, Pair("ab".to_string(), "42".to_string()));
1587		/// ```
1588		fn ref_bind<'a, A: 'a, B: 'a>(
1589			fa: &Apply!(<Self as Kind!( type Of<'a, T: 'a>: 'a; )>::Of<'a, A>),
1590			f: impl Fn(&A) -> Apply!(<Self as Kind!( type Of<'a, T: 'a>: 'a; )>::Of<'a, B>) + 'a,
1591		) -> Apply!(<Self as Kind!( type Of<'a, T: 'a>: 'a; )>::Of<'a, B>) {
1592			let Pair(next_first, next_second) = f(&fa.1);
1593			Pair(Semigroup::append(fa.0.clone(), next_first), next_second)
1594		}
1595	}
1596
1597	// PairSecondAppliedBrand<Second> (Functor over First)
1598
1599	impl_kind! {
1600		#[no_inferable_brand]
1601		#[document_type_parameters("The type of the second value in the pair.")]
1602		impl<Second: 'static> for PairSecondAppliedBrand<Second> {
1603			type Of<'a, A: 'a>: 'a = Pair<A, Second>;
1604		}
1605	}
1606
1607	#[document_type_parameters("The type of the second value in the pair.")]
1608	impl<Second: 'static> Functor for PairSecondAppliedBrand<Second> {
1609		/// Maps a function over the first value in the pair.
1610		///
1611		/// 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.
1612		#[document_signature]
1613		///
1614		#[document_type_parameters(
1615			"The lifetime of the values.",
1616			"The type of the first value.",
1617			"The type of the result of applying the function."
1618		)]
1619		///
1620		#[document_parameters("The function to apply to the first value.", "The pair to map over.")]
1621		///
1622		#[document_returns(
1623			"A new pair containing the result of applying the function to the first value."
1624		)]
1625		///
1626		#[document_examples]
1627		///
1628		/// ```
1629		/// use fp_library::{
1630		/// 	brands::*,
1631		/// 	functions::*,
1632		/// 	types::*,
1633		/// };
1634		///
1635		/// assert_eq!(
1636		/// 	explicit::map::<PairSecondAppliedBrand<_>, _, _, _, _>(|x: i32| x * 2, Pair(5, 1)),
1637		/// 	Pair(10, 1)
1638		/// );
1639		/// ```
1640		fn map<'a, A: 'a, B: 'a>(
1641			func: impl Fn(A) -> B + 'a,
1642			fa: Apply!(<Self as Kind!( type Of<'a, T: 'a>: 'a; )>::Of<'a, A>),
1643		) -> Apply!(<Self as Kind!( type Of<'a, T: 'a>: 'a; )>::Of<'a, B>) {
1644			fa.map_first(func)
1645		}
1646	}
1647
1648	#[document_type_parameters("The type of the second value in the pair.")]
1649	impl<Second: Clone + 'static> Lift for PairSecondAppliedBrand<Second>
1650	where
1651		Second: Semigroup,
1652	{
1653		/// Lifts a binary function into the pair context (over first).
1654		///
1655		/// 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.
1656		#[document_signature]
1657		///
1658		#[document_type_parameters(
1659			"The lifetime of the values.",
1660			"The type of the first first value.",
1661			"The type of the second first value.",
1662			"The type of the result first value."
1663		)]
1664		///
1665		#[document_parameters(
1666			"The binary function to apply to the first values.",
1667			"The first pair.",
1668			"The second pair."
1669		)]
1670		///
1671		#[document_returns(
1672			"A new pair where the first values are combined using `f` and the second values are combined using `Semigroup::append`."
1673		)]
1674		#[document_examples]
1675		///
1676		/// ```
1677		/// use fp_library::{
1678		/// 	brands::*,
1679		/// 	functions::*,
1680		/// 	types::*,
1681		/// };
1682		///
1683		/// assert_eq!(
1684		/// 	explicit::lift2::<PairSecondAppliedBrand<String>, _, _, _, _, _, _>(
1685		/// 		|x, y| x + y,
1686		/// 		Pair(1, "a".to_string()),
1687		/// 		Pair(2, "b".to_string())
1688		/// 	),
1689		/// 	Pair(3, "ab".to_string())
1690		/// );
1691		/// ```
1692		fn lift2<'a, A, B, C>(
1693			func: impl Fn(A, B) -> C + 'a,
1694			fa: Apply!(<Self as Kind!( type Of<'a, T: 'a>: 'a; )>::Of<'a, A>),
1695			fb: Apply!(<Self as Kind!( type Of<'a, T: 'a>: 'a; )>::Of<'a, B>),
1696		) -> Apply!(<Self as Kind!( type Of<'a, T: 'a>: 'a; )>::Of<'a, C>)
1697		where
1698			A: Clone + 'a,
1699			B: Clone + 'a,
1700			C: 'a, {
1701			Pair(func(fa.0, fb.0), Semigroup::append(fa.1, fb.1))
1702		}
1703	}
1704
1705	#[document_type_parameters("The type of the second value in the pair.")]
1706	impl<Second: Clone + 'static> Pointed for PairSecondAppliedBrand<Second>
1707	where
1708		Second: Monoid,
1709	{
1710		/// Wraps a value in a pair (with empty second).
1711		///
1712		/// This method wraps a value in a pair, using the `Monoid::empty()` value for the second element.
1713		#[document_signature]
1714		///
1715		#[document_type_parameters("The lifetime of the value.", "The type of the value to wrap.")]
1716		///
1717		#[document_parameters("The value to wrap.")]
1718		///
1719		#[document_returns("A pair containing `a` and the empty value of the second type.")]
1720		///
1721		#[document_examples]
1722		///
1723		/// ```
1724		/// use fp_library::{
1725		/// 	brands::*,
1726		/// 	functions::*,
1727		/// 	types::*,
1728		/// };
1729		///
1730		/// assert_eq!(pure::<PairSecondAppliedBrand<String>, _>(5), Pair(5, "".to_string()));
1731		/// ```
1732		fn pure<'a, A: 'a>(a: A) -> Apply!(<Self as Kind!( type Of<'a, T: 'a>: 'a; )>::Of<'a, A>) {
1733			Pair(a, Monoid::empty())
1734		}
1735	}
1736
1737	#[document_type_parameters("The type of the second value in the pair.")]
1738	impl<Second: Clone + Semigroup + 'static> ApplyFirst for PairSecondAppliedBrand<Second> {}
1739
1740	#[document_type_parameters("The type of the second value in the pair.")]
1741	impl<Second: Clone + Semigroup + 'static> ApplySecond for PairSecondAppliedBrand<Second> {}
1742
1743	#[document_type_parameters("The type of the second value in the pair.")]
1744	impl<Second: Clone + 'static> Semiapplicative for PairSecondAppliedBrand<Second>
1745	where
1746		Second: Semigroup,
1747	{
1748		/// Applies a wrapped function to a wrapped value (over first).
1749		///
1750		/// This method applies a function wrapped in a result (as error) to a value wrapped in a result (as error).
1751		#[document_signature]
1752		///
1753		#[document_type_parameters(
1754			"The lifetime of the values.",
1755			"The brand of the cloneable function wrapper.",
1756			"The type of the input value.",
1757			"The type of the output value."
1758		)]
1759		///
1760		#[document_parameters(
1761			"The pair containing the function (in Err).",
1762			"The pair containing the value (in Err)."
1763		)]
1764		///
1765		#[document_returns(
1766			"`Err(f(a))` if both are `Err`, otherwise the first success encountered."
1767		)]
1768		#[document_examples]
1769		///
1770		/// ```
1771		/// use fp_library::{
1772		/// 	brands::*,
1773		/// 	functions::*,
1774		/// 	types::*,
1775		/// };
1776		///
1777		/// let f = Pair(lift_fn_new::<RcFnBrand, _, _>(|x: i32| x * 2), "a".to_string());
1778		/// assert_eq!(
1779		/// 	apply::<RcFnBrand, PairSecondAppliedBrand<String>, _, _>(f, Pair(5, "b".to_string())),
1780		/// 	Pair(10, "ab".to_string())
1781		/// );
1782		/// ```
1783		fn apply<'a, FnBrand: 'a + CloneFn, A: 'a + Clone, B: 'a>(
1784			ff: Apply!(<Self as Kind!( type Of<'a, T: 'a>: 'a; )>::Of<'a, <FnBrand as CloneFn>::Of<'a, A, B>>),
1785			fa: Apply!(<Self as Kind!( type Of<'a, T: 'a>: 'a; )>::Of<'a, A>),
1786		) -> Apply!(<Self as Kind!( type Of<'a, T: 'a>: 'a; )>::Of<'a, B>) {
1787			Pair(ff.0(fa.0), Semigroup::append(ff.1, fa.1))
1788		}
1789	}
1790
1791	#[document_type_parameters("The type of the second value in the pair.")]
1792	impl<Second: Clone + 'static> Semimonad for PairSecondAppliedBrand<Second>
1793	where
1794		Second: Semigroup,
1795	{
1796		/// Chains pair computations (over first).
1797		///
1798		/// This method chains two computations, where the second computation depends on the result of the first (over error).
1799		#[document_signature]
1800		///
1801		#[document_type_parameters(
1802			"The lifetime of the values.",
1803			"The type of the result of the first computation.",
1804			"The type of the result of the second computation."
1805		)]
1806		///
1807		#[document_parameters("The first result.", "The function to apply to the error value.")]
1808		///
1809		#[document_returns(
1810			"The result of applying `f` to the error if `ma` is `Err`, otherwise the original success."
1811		)]
1812		///
1813		#[document_examples]
1814		///
1815		/// ```
1816		/// use fp_library::{
1817		/// 	brands::*,
1818		/// 	functions::*,
1819		/// 	types::*,
1820		/// };
1821		///
1822		/// assert_eq!(
1823		/// 	explicit::bind::<PairSecondAppliedBrand<String>, _, _, _, _>(
1824		/// 		Pair(5, "a".to_string()),
1825		/// 		|x| Pair(x * 2, "b".to_string())
1826		/// 	),
1827		/// 	Pair(10, "ab".to_string())
1828		/// );
1829		/// ```
1830		fn bind<'a, A: 'a, B: 'a>(
1831			ma: Apply!(<Self as Kind!( type Of<'a, T: 'a>: 'a; )>::Of<'a, A>),
1832			func: impl Fn(A) -> Apply!(<Self as Kind!( type Of<'a, T: 'a>: 'a; )>::Of<'a, B>) + 'a,
1833		) -> Apply!(<Self as Kind!( type Of<'a, T: 'a>: 'a; )>::Of<'a, B>) {
1834			ma.bind_first(func)
1835		}
1836	}
1837
1838	/// [`MonadRec`] implementation for [`PairSecondAppliedBrand`].
1839	#[document_type_parameters("The type of the second value in the pair.")]
1840	impl<Second: Clone + 'static> MonadRec for PairSecondAppliedBrand<Second>
1841	where
1842		Second: Monoid,
1843	{
1844		/// Performs tail-recursive monadic computation over the first value, accumulating the second.
1845		///
1846		/// Iteratively applies the step function. Each iteration produces a pair
1847		/// whose second value is combined with the running accumulator via
1848		/// [`Semigroup::append`]. If the step returns `ControlFlow::Continue(a)`, the loop
1849		/// continues with the new state. If it returns `ControlFlow::Break(b)`, the
1850		/// computation completes with `b` and the accumulated second value.
1851		#[document_signature]
1852		///
1853		#[document_type_parameters(
1854			"The lifetime of the computation.",
1855			"The type of the initial value and loop state.",
1856			"The type of the result."
1857		)]
1858		///
1859		#[document_parameters("The step function.", "The initial value.")]
1860		///
1861		#[document_returns("A pair with the final result and the accumulated second value.")]
1862		///
1863		#[document_examples]
1864		///
1865		/// ```
1866		/// use {
1867		/// 	core::ops::ControlFlow,
1868		/// 	fp_library::{
1869		/// 		brands::*,
1870		/// 		functions::*,
1871		/// 		types::*,
1872		/// 	},
1873		/// };
1874		///
1875		/// let result = tail_rec_m::<PairSecondAppliedBrand<String>, _, _>(
1876		/// 	|n| {
1877		/// 		if n < 3 {
1878		/// 			Pair(ControlFlow::Continue(n + 1), format!("{n},"))
1879		/// 		} else {
1880		/// 			Pair(ControlFlow::Break(n), format!("{n}"))
1881		/// 		}
1882		/// 	},
1883		/// 	0,
1884		/// );
1885		/// assert_eq!(result, Pair(3, "0,1,2,3".to_string()));
1886		/// ```
1887		fn tail_rec_m<'a, A: 'a, B: 'a>(
1888			func: impl Fn(
1889				A,
1890			)
1891				-> Apply!(<Self as Kind!( type Of<'a, T: 'a>: 'a; )>::Of<'a, ControlFlow<B, A>>)
1892			+ 'a,
1893			initial: A,
1894		) -> Apply!(<Self as Kind!( type Of<'a, T: 'a>: 'a; )>::Of<'a, B>) {
1895			let mut acc: Second = Monoid::empty();
1896			let mut current = initial;
1897			loop {
1898				let Pair(step, second) = func(current);
1899				acc = Semigroup::append(acc, second);
1900				match step {
1901					ControlFlow::Continue(next) => current = next,
1902					ControlFlow::Break(b) => return Pair(b, acc),
1903				}
1904			}
1905		}
1906	}
1907
1908	#[document_type_parameters("The type of the second value in the pair.")]
1909	impl<Second: 'static> Foldable for PairSecondAppliedBrand<Second> {
1910		/// Folds the pair from the right (over first).
1911		///
1912		/// This method performs a right-associative fold of the result (over error).
1913		#[document_signature]
1914		///
1915		#[document_type_parameters(
1916			"The lifetime of the values.",
1917			"The brand of the cloneable function to use.",
1918			"The type of the elements in the structure.",
1919			"The type of the accumulator."
1920		)]
1921		///
1922		#[document_parameters("The folding function.", "The initial value.", "The result to fold.")]
1923		///
1924		#[document_returns("`func(a, initial)` if `fa` is `Err(a)`, otherwise `initial`.")]
1925		///
1926		#[document_examples]
1927		///
1928		/// ```
1929		/// use fp_library::{
1930		/// 	brands::*,
1931		/// 	functions::*,
1932		/// 	types::*,
1933		/// };
1934		///
1935		/// assert_eq!(
1936		/// 	explicit::fold_right::<RcFnBrand, PairSecondAppliedBrand<()>, _, _, _, _>(
1937		/// 		|x, acc| x + acc,
1938		/// 		0,
1939		/// 		Pair(5, ())
1940		/// 	),
1941		/// 	5
1942		/// );
1943		/// ```
1944		fn fold_right<'a, FnBrand, A: 'a + Clone, B: 'a>(
1945			func: impl Fn(A, B) -> B + 'a,
1946			initial: B,
1947			fa: Apply!(<Self as Kind!( type Of<'a, T: 'a>: 'a; )>::Of<'a, A>),
1948		) -> B
1949		where
1950			FnBrand: CloneFn + 'a, {
1951			func(fa.0, initial)
1952		}
1953
1954		/// Folds the pair from the left (over first).
1955		///
1956		/// This method performs a left-associative fold of the result (over error).
1957		#[document_signature]
1958		///
1959		#[document_type_parameters(
1960			"The lifetime of the values.",
1961			"The brand of the cloneable function to use.",
1962			"The type of the elements in the structure.",
1963			"The type of the accumulator."
1964		)]
1965		///
1966		#[document_parameters("The folding function.", "The initial value.", "The result to fold.")]
1967		///
1968		#[document_returns("`func(initial, a)` if `fa` is `Err(a)`, otherwise `initial`.")]
1969		///
1970		#[document_examples]
1971		///
1972		/// ```
1973		/// use fp_library::{
1974		/// 	brands::*,
1975		/// 	functions::*,
1976		/// 	types::*,
1977		/// };
1978		///
1979		/// assert_eq!(
1980		/// 	explicit::fold_left::<RcFnBrand, PairSecondAppliedBrand<()>, _, _, _, _>(
1981		/// 		|acc, x| acc + x,
1982		/// 		0,
1983		/// 		Pair(5, ())
1984		/// 	),
1985		/// 	5
1986		/// );
1987		/// ```
1988		fn fold_left<'a, FnBrand, A: 'a + Clone, B: 'a>(
1989			func: impl Fn(B, A) -> B + 'a,
1990			initial: B,
1991			fa: Apply!(<Self as Kind!( type Of<'a, T: 'a>: 'a; )>::Of<'a, A>),
1992		) -> B
1993		where
1994			FnBrand: CloneFn + 'a, {
1995			func(initial, fa.0)
1996		}
1997
1998		/// Maps the value to a monoid and returns it (over first).
1999		///
2000		/// This method maps the element of the result to a monoid and then returns it (over error).
2001		#[document_signature]
2002		///
2003		#[document_type_parameters(
2004			"The lifetime of the values.",
2005			"The brand of the cloneable function to use.",
2006			"The type of the elements in the structure.",
2007			"The type of the monoid."
2008		)]
2009		///
2010		#[document_parameters("The mapping function.", "The result to fold.")]
2011		///
2012		#[document_returns("`func(a)` if `fa` is `Err(a)`, otherwise `M::empty()`.")]
2013		///
2014		#[document_examples]
2015		///
2016		/// ```
2017		/// use fp_library::{
2018		/// 	brands::*,
2019		/// 	functions::*,
2020		/// 	types::*,
2021		/// };
2022		///
2023		/// assert_eq!(
2024		/// 	explicit::fold_map::<RcFnBrand, PairSecondAppliedBrand<()>, _, _, _, _>(
2025		/// 		|x: i32| x.to_string(),
2026		/// 		Pair(5, ())
2027		/// 	),
2028		/// 	"5".to_string()
2029		/// );
2030		/// ```
2031		fn fold_map<'a, FnBrand, A: 'a + Clone, M>(
2032			func: impl Fn(A) -> M + 'a,
2033			fa: Apply!(<Self as Kind!( type Of<'a, T: 'a>: 'a; )>::Of<'a, A>),
2034		) -> M
2035		where
2036			M: Monoid + 'a,
2037			FnBrand: CloneFn + 'a, {
2038			func(fa.0)
2039		}
2040	}
2041
2042	#[document_type_parameters("The type of the second value in the pair.")]
2043	impl<Second: Clone + 'static> Traversable for PairSecondAppliedBrand<Second> {
2044		/// Traverses the pair with an applicative function (over first).
2045		///
2046		/// This method maps the element of the result to a computation, evaluates it, and combines the result into an applicative context (over error).
2047		#[document_signature]
2048		///
2049		#[document_type_parameters(
2050			"The lifetime of the values.",
2051			"The type of the elements in the traversable structure.",
2052			"The type of the elements in the resulting traversable structure.",
2053			"The applicative context."
2054		)]
2055		///
2056		#[document_parameters("The function to apply.", "The result to traverse.")]
2057		///
2058		#[document_returns("The result wrapped in the applicative context.")]
2059		///
2060		#[document_examples]
2061		///
2062		/// ```
2063		/// use fp_library::{
2064		/// 	brands::*,
2065		/// 	functions::*,
2066		/// 	types::*,
2067		/// };
2068		///
2069		/// assert_eq!(
2070		/// 	explicit::traverse::<RcFnBrand, PairSecondAppliedBrand<()>, _, _, OptionBrand, _, _>(
2071		/// 		|x| Some(x * 2),
2072		/// 		Pair(5, ())
2073		/// 	),
2074		/// 	Some(Pair(10, ()))
2075		/// );
2076		/// ```
2077		fn traverse<'a, A: 'a + Clone, B: 'a + Clone, F: Applicative>(
2078			func: impl Fn(A) -> Apply!(<F as Kind!( type Of<'a, T: 'a>: 'a; )>::Of<'a, B>) + 'a,
2079			ta: Apply!(<Self as Kind!( type Of<'a, T: 'a>: 'a; )>::Of<'a, A>),
2080		) -> 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>)>)
2081		where
2082			Apply!(<Self as Kind!( type Of<'a, T: 'a>: 'a; )>::Of<'a, B>): Clone, {
2083			let Pair(first, second) = ta;
2084			F::map(move |b| Pair(b, second.clone()), func(first))
2085		}
2086
2087		/// Sequences a pair of applicative (over first).
2088		///
2089		/// This method evaluates the computation inside the result and accumulates the result into an applicative context (over error).
2090		#[document_signature]
2091		///
2092		#[document_type_parameters(
2093			"The lifetime of the values.",
2094			"The type of the elements in the traversable structure.",
2095			"The applicative context."
2096		)]
2097		///
2098		#[document_parameters("The result containing the applicative value.")]
2099		///
2100		#[document_returns("The result wrapped in the applicative context.")]
2101		///
2102		#[document_examples]
2103		///
2104		/// ```
2105		/// use fp_library::{
2106		/// 	brands::*,
2107		/// 	functions::*,
2108		/// 	types::*,
2109		/// };
2110		///
2111		/// assert_eq!(
2112		/// 	sequence::<PairSecondAppliedBrand<()>, _, OptionBrand>(Pair(Some(5), ())),
2113		/// 	Some(Pair(5, ()))
2114		/// );
2115		/// ```
2116		fn sequence<'a, A: 'a + Clone, F: Applicative>(
2117			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>)>)
2118		) -> 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>)>)
2119		where
2120			Apply!(<F as Kind!( type Of<'a, T: 'a>: 'a; )>::Of<'a, A>): Clone,
2121			Apply!(<Self as Kind!( type Of<'a, T: 'a>: 'a; )>::Of<'a, A>): Clone, {
2122			let Pair(first, second) = ta;
2123			F::map(move |a| Pair(a, second.clone()), first)
2124		}
2125	}
2126	// -- By-reference trait implementations for PairSecondAppliedBrand --
2127
2128	#[document_type_parameters("The type of the second value in the pair.")]
2129	impl<Second: Clone + 'static> RefFunctor for PairSecondAppliedBrand<Second> {
2130		/// Maps a function over the first value in the pair by reference.
2131		#[document_signature]
2132		#[document_type_parameters("The lifetime.", "The input type.", "The output type.")]
2133		#[document_parameters("The function.", "The pair.")]
2134		#[document_returns("A new pair with the mapped first value.")]
2135		#[document_examples]
2136		///
2137		/// ```
2138		/// use fp_library::{
2139		/// 	brands::*,
2140		/// 	functions::*,
2141		/// 	types::*,
2142		/// };
2143		/// assert_eq!(
2144		/// 	explicit::map::<PairSecondAppliedBrand<_>, _, _, _, _>(|x: &i32| *x * 2, &Pair(5, 1)),
2145		/// 	Pair(10, 1)
2146		/// );
2147		/// ```
2148		fn ref_map<'a, A: 'a, B: 'a>(
2149			func: impl Fn(&A) -> B + 'a,
2150			fa: &Apply!(<Self as Kind!( type Of<'a, T: 'a>: 'a; )>::Of<'a, A>),
2151		) -> Apply!(<Self as Kind!( type Of<'a, T: 'a>: 'a; )>::Of<'a, B>) {
2152			Pair(func(&fa.0), fa.1.clone())
2153		}
2154	}
2155
2156	#[document_type_parameters("The type of the second value in the pair.")]
2157	impl<Second: Clone + 'static> RefFoldable for PairSecondAppliedBrand<Second> {
2158		/// Folds the pair by reference (over first).
2159		#[document_signature]
2160		#[document_type_parameters(
2161			"The lifetime.",
2162			"The brand.",
2163			"The element type.",
2164			"The monoid type."
2165		)]
2166		#[document_parameters("The mapping function.", "The pair.")]
2167		#[document_returns("The monoid value.")]
2168		#[document_examples]
2169		///
2170		/// ```
2171		/// use fp_library::{
2172		/// 	brands::*,
2173		/// 	functions::*,
2174		/// 	types::*,
2175		/// };
2176		/// let result = explicit::fold_map::<RcFnBrand, PairSecondAppliedBrand<()>, _, _, _, _>(
2177		/// 	|x: &i32| x.to_string(),
2178		/// 	&Pair(5, ()),
2179		/// );
2180		/// assert_eq!(result, "5");
2181		/// ```
2182		fn ref_fold_map<'a, FnBrand, A: 'a + Clone, M>(
2183			func: impl Fn(&A) -> M + 'a,
2184			fa: &Apply!(<Self as Kind!( type Of<'a, T: 'a>: 'a; )>::Of<'a, A>),
2185		) -> M
2186		where
2187			FnBrand: LiftFn + 'a,
2188			M: Monoid + 'a, {
2189			func(&fa.0)
2190		}
2191	}
2192
2193	#[document_type_parameters("The type of the second value in the pair.")]
2194	impl<Second: Clone + 'static> RefTraversable for PairSecondAppliedBrand<Second> {
2195		/// Traverses the pair by reference (over first).
2196		#[document_signature]
2197		#[document_type_parameters(
2198			"The lifetime.",
2199			"The brand.",
2200			"The input type.",
2201			"The output type.",
2202			"The applicative."
2203		)]
2204		#[document_parameters("The function.", "The pair.")]
2205		#[document_returns("The traversed result.")]
2206		#[document_examples]
2207		///
2208		/// ```
2209		/// use fp_library::{
2210		/// 	brands::*,
2211		/// 	functions::*,
2212		/// 	types::*,
2213		/// };
2214		/// let result: Option<Pair<String, ()>> =
2215		/// 	ref_traverse::<PairSecondAppliedBrand<()>, RcFnBrand, _, _, OptionBrand>(
2216		/// 		|x: &i32| Some(x.to_string()),
2217		/// 		&Pair(42, ()),
2218		/// 	);
2219		/// assert_eq!(result, Some(Pair("42".to_string(), ())));
2220		/// ```
2221		fn ref_traverse<'a, FnBrand, A: 'a + Clone, B: 'a + Clone, F: Applicative>(
2222			func: impl Fn(&A) -> Apply!(<F as Kind!( type Of<'a, T: 'a>: 'a; )>::Of<'a, B>) + 'a,
2223			ta: &Apply!(<Self as Kind!( type Of<'a, T: 'a>: 'a; )>::Of<'a, A>),
2224		) -> 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>)>)
2225		where
2226			FnBrand: LiftFn + 'a,
2227			Apply!(<Self as Kind!( type Of<'a, T: 'a>: 'a; )>::Of<'a, B>): Clone,
2228			Apply!(<F as Kind!( type Of<'a, T: 'a>: 'a; )>::Of<'a, B>): Clone, {
2229			let second = ta.1.clone();
2230			F::map(move |a| Pair(a, second.clone()), func(&ta.0))
2231		}
2232	}
2233
2234	#[document_type_parameters("The type of the second value in the pair.")]
2235	impl<Second: Clone + 'static> RefPointed for PairSecondAppliedBrand<Second>
2236	where
2237		Second: Monoid,
2238	{
2239		/// Creates a pair from a reference by cloning (with empty second).
2240		#[document_signature]
2241		#[document_type_parameters("The lifetime.", "The value type.")]
2242		#[document_parameters("The reference to wrap.")]
2243		#[document_returns("A pair containing a clone of the value and `Monoid::empty()`.")]
2244		#[document_examples]
2245		///
2246		/// ```
2247		/// use fp_library::{
2248		/// 	brands::*,
2249		/// 	functions::*,
2250		/// 	types::*,
2251		/// };
2252		///
2253		/// let x = 42;
2254		/// let result: Pair<i32, String> = ref_pure::<PairSecondAppliedBrand<String>, _>(&x);
2255		/// assert_eq!(result, Pair(42, "".to_string()));
2256		/// ```
2257		fn ref_pure<'a, A: Clone + 'a>(
2258			a: &A
2259		) -> Apply!(<Self as Kind!( type Of<'a, T: 'a>: 'a; )>::Of<'a, A>) {
2260			Pair(a.clone(), Monoid::empty())
2261		}
2262	}
2263
2264	#[document_type_parameters("The type of the second value in the pair.")]
2265	impl<Second: Clone + 'static> RefLift for PairSecondAppliedBrand<Second>
2266	where
2267		Second: Semigroup,
2268	{
2269		/// Combines two pairs with a by-reference binary function (over first).
2270		#[document_signature]
2271		#[document_type_parameters("The lifetime.", "First input.", "Second input.", "Output.")]
2272		#[document_parameters("The binary function.", "The first pair.", "The second pair.")]
2273		#[document_returns("A pair with the function result and combined second values.")]
2274		#[document_examples]
2275		///
2276		/// ```
2277		/// use fp_library::{
2278		/// 	brands::*,
2279		/// 	functions::*,
2280		/// 	types::*,
2281		/// };
2282		///
2283		/// let result = explicit::lift2::<PairSecondAppliedBrand<String>, _, _, _, _, _, _>(
2284		/// 	|a: &i32, b: &i32| *a + *b,
2285		/// 	&Pair(1, "a".to_string()),
2286		/// 	&Pair(2, "b".to_string()),
2287		/// );
2288		/// assert_eq!(result, Pair(3, "ab".to_string()));
2289		/// ```
2290		fn ref_lift2<'a, A: 'a, B: 'a, C: 'a>(
2291			func: impl Fn(&A, &B) -> C + 'a,
2292			fa: &Apply!(<Self as Kind!( type Of<'a, T: 'a>: 'a; )>::Of<'a, A>),
2293			fb: &Apply!(<Self as Kind!( type Of<'a, T: 'a>: 'a; )>::Of<'a, B>),
2294		) -> Apply!(<Self as Kind!( type Of<'a, T: 'a>: 'a; )>::Of<'a, C>) {
2295			Pair(func(&fa.0, &fb.0), Semigroup::append(fa.1.clone(), fb.1.clone()))
2296		}
2297	}
2298
2299	#[document_type_parameters("The type of the second value in the pair.")]
2300	impl<Second: Clone + 'static> RefSemiapplicative for PairSecondAppliedBrand<Second>
2301	where
2302		Second: Semigroup,
2303	{
2304		/// Applies a wrapped by-ref function to a pair value (over first).
2305		#[document_signature]
2306		#[document_type_parameters(
2307			"The lifetime.",
2308			"The function brand.",
2309			"The input type.",
2310			"The output type."
2311		)]
2312		#[document_parameters(
2313			"The pair containing the function.",
2314			"The pair containing the value."
2315		)]
2316		#[document_returns("A pair with the function result and combined second values.")]
2317		#[document_examples]
2318		///
2319		/// ```
2320		/// use fp_library::{
2321		/// 	brands::*,
2322		/// 	functions::*,
2323		/// 	types::*,
2324		/// };
2325		///
2326		/// let f: std::rc::Rc<dyn Fn(&i32) -> i32> = std::rc::Rc::new(|x: &i32| *x * 2);
2327		/// let result = ref_apply::<RcFnBrand, PairSecondAppliedBrand<String>, _, _>(
2328		/// 	&Pair(f, "a".to_string()),
2329		/// 	&Pair(5, "b".to_string()),
2330		/// );
2331		/// assert_eq!(result, Pair(10, "ab".to_string()));
2332		/// ```
2333		fn ref_apply<'a, FnBrand: 'a + CloneFn<Ref>, A: 'a, B: 'a>(
2334			ff: &Apply!(<Self as Kind!( type Of<'a, T: 'a>: 'a; )>::Of<'a, <FnBrand as CloneFn<Ref>>::Of<'a, A, B>>),
2335			fa: &Apply!(<Self as Kind!( type Of<'a, T: 'a>: 'a; )>::Of<'a, A>),
2336		) -> Apply!(<Self as Kind!( type Of<'a, T: 'a>: 'a; )>::Of<'a, B>) {
2337			Pair((*ff.0)(&fa.0), Semigroup::append(ff.1.clone(), fa.1.clone()))
2338		}
2339	}
2340
2341	#[document_type_parameters("The type of the second value in the pair.")]
2342	impl<Second: Clone + 'static> RefSemimonad for PairSecondAppliedBrand<Second>
2343	where
2344		Second: Semigroup,
2345	{
2346		/// Chains pair computations by reference (over first).
2347		#[document_signature]
2348		#[document_type_parameters("The lifetime.", "The input type.", "The output type.")]
2349		#[document_parameters("The input pair.", "The function to apply by reference.")]
2350		#[document_returns("A pair with combined second values.")]
2351		#[document_examples]
2352		///
2353		/// ```
2354		/// use fp_library::{
2355		/// 	brands::*,
2356		/// 	functions::*,
2357		/// 	types::*,
2358		/// };
2359		///
2360		/// let result: Pair<String, String> = explicit::bind::<PairSecondAppliedBrand<String>, _, _, _, _>(
2361		/// 	&Pair(42, "a".to_string()),
2362		/// 	|x: &i32| Pair(x.to_string(), "b".to_string()),
2363		/// );
2364		/// assert_eq!(result, Pair("42".to_string(), "ab".to_string()));
2365		/// ```
2366		fn ref_bind<'a, A: 'a, B: 'a>(
2367			fa: &Apply!(<Self as Kind!( type Of<'a, T: 'a>: 'a; )>::Of<'a, A>),
2368			f: impl Fn(&A) -> Apply!(<Self as Kind!( type Of<'a, T: 'a>: 'a; )>::Of<'a, B>) + 'a,
2369		) -> Apply!(<Self as Kind!( type Of<'a, T: 'a>: 'a; )>::Of<'a, B>) {
2370			let Pair(next_first, next_second) = f(&fa.0);
2371			Pair(next_first, Semigroup::append(fa.1.clone(), next_second))
2372		}
2373	}
2374}
2375pub use inner::*;
2376
2377#[cfg(test)]
2378mod tests {
2379	use {
2380		super::inner::*,
2381		crate::{
2382			brands::*,
2383			classes::*,
2384			functions::*,
2385		},
2386		quickcheck_macros::quickcheck,
2387	};
2388
2389	// Bifunctor Tests
2390
2391	/// Tests `bimap` on `Pair`.
2392	#[test]
2393	fn test_bimap() {
2394		let x = Pair(1, 5);
2395		assert_eq!(
2396			explicit::bimap::<PairBrand, _, _, _, _, _, _>((|a| a + 1, |b| b * 2), x),
2397			Pair(2, 10)
2398		);
2399	}
2400
2401	// Bifunctor Laws
2402
2403	/// Tests the identity law for Bifunctor.
2404	#[quickcheck]
2405	fn bifunctor_identity(
2406		first: String,
2407		second: i32,
2408	) -> bool {
2409		let x = Pair(first, second);
2410		explicit::bimap::<PairBrand, _, _, _, _, _, _>((identity, identity), x.clone()) == x
2411	}
2412
2413	/// Tests the composition law for Bifunctor.
2414	#[quickcheck]
2415	fn bifunctor_composition(
2416		first: i32,
2417		second: i32,
2418	) -> bool {
2419		let x = Pair(first, second);
2420		let f = |x: i32| x.wrapping_add(1);
2421		let g = |x: i32| x.wrapping_mul(2);
2422		let h = |x: i32| x.wrapping_sub(1);
2423		let i = |x: i32| if x == 0 { 0 } else { x.wrapping_div(2) };
2424
2425		explicit::bimap::<PairBrand, _, _, _, _, _, _>((compose(f, g), compose(h, i)), x)
2426			== explicit::bimap::<PairBrand, _, _, _, _, _, _>(
2427				(f, h),
2428				explicit::bimap::<PairBrand, _, _, _, _, _, _>((g, i), x),
2429			)
2430	}
2431
2432	// Functor Laws
2433
2434	/// Tests the identity law for Functor.
2435	#[quickcheck]
2436	fn functor_identity(
2437		first: String,
2438		second: i32,
2439	) -> bool {
2440		let x = Pair(first, second);
2441		explicit::map::<PairFirstAppliedBrand<String>, _, _, _, _>(identity, x.clone()) == x
2442	}
2443
2444	/// Tests the composition law for Functor.
2445	#[quickcheck]
2446	fn functor_composition(
2447		first: String,
2448		second: i32,
2449	) -> bool {
2450		let x = Pair(first, second);
2451		let f = |x: i32| x.wrapping_add(1);
2452		let g = |x: i32| x.wrapping_mul(2);
2453		explicit::map::<PairFirstAppliedBrand<String>, _, _, _, _>(compose(f, g), x.clone())
2454			== explicit::map::<PairFirstAppliedBrand<String>, _, _, _, _>(
2455				f,
2456				explicit::map::<PairFirstAppliedBrand<String>, _, _, _, _>(g, x),
2457			)
2458	}
2459
2460	// Applicative Laws
2461
2462	/// Tests the identity law for Applicative.
2463	#[quickcheck]
2464	fn applicative_identity(
2465		first: String,
2466		second: i32,
2467	) -> bool {
2468		let v = Pair(first, second);
2469		apply::<RcFnBrand, PairFirstAppliedBrand<String>, _, _>(
2470			pure::<PairFirstAppliedBrand<String>, _>(<RcFnBrand as LiftFn>::new(identity)),
2471			v.clone(),
2472		) == v
2473	}
2474
2475	/// Tests the homomorphism law for Applicative.
2476	#[quickcheck]
2477	fn applicative_homomorphism(x: i32) -> bool {
2478		let f = |x: i32| x.wrapping_mul(2);
2479		apply::<RcFnBrand, PairFirstAppliedBrand<String>, _, _>(
2480			pure::<PairFirstAppliedBrand<String>, _>(<RcFnBrand as LiftFn>::new(f)),
2481			pure::<PairFirstAppliedBrand<String>, _>(x),
2482		) == pure::<PairFirstAppliedBrand<String>, _>(f(x))
2483	}
2484
2485	/// Tests the composition law for Applicative.
2486	#[quickcheck]
2487	fn applicative_composition(
2488		w_first: String,
2489		w_second: i32,
2490		u_seed: i32,
2491		v_seed: i32,
2492	) -> bool {
2493		let w = Pair(w_first, w_second);
2494
2495		let u_fn = <RcFnBrand as LiftFn>::new(move |x: i32| x.wrapping_add(u_seed));
2496		let u = pure::<PairFirstAppliedBrand<String>, _>(u_fn);
2497
2498		let v_fn = <RcFnBrand as LiftFn>::new(move |x: i32| x.wrapping_mul(v_seed));
2499		let v = pure::<PairFirstAppliedBrand<String>, _>(v_fn);
2500
2501		// RHS: u <*> (v <*> w)
2502		let vw = apply::<RcFnBrand, PairFirstAppliedBrand<String>, _, _>(v.clone(), w.clone());
2503		let rhs = apply::<RcFnBrand, PairFirstAppliedBrand<String>, _, _>(u.clone(), vw);
2504
2505		// LHS: pure(compose) <*> u <*> v <*> w
2506		let compose_fn = <RcFnBrand as LiftFn>::new(|f: std::rc::Rc<dyn Fn(i32) -> i32>| {
2507			let f = f.clone();
2508			<RcFnBrand as LiftFn>::new(move |g: std::rc::Rc<dyn Fn(i32) -> i32>| {
2509				let f = f.clone();
2510				let g = g.clone();
2511				<RcFnBrand as LiftFn>::new(move |x| f(g(x)))
2512			})
2513		});
2514
2515		let pure_compose = pure::<PairFirstAppliedBrand<String>, _>(compose_fn);
2516		let u_applied = apply::<RcFnBrand, PairFirstAppliedBrand<String>, _, _>(pure_compose, u);
2517		let uv = apply::<RcFnBrand, PairFirstAppliedBrand<String>, _, _>(u_applied, v);
2518		let lhs = apply::<RcFnBrand, PairFirstAppliedBrand<String>, _, _>(uv, w);
2519
2520		lhs == rhs
2521	}
2522
2523	/// Tests the interchange law for Applicative.
2524	#[quickcheck]
2525	fn applicative_interchange(
2526		y: i32,
2527		u_seed: i32,
2528	) -> bool {
2529		// u <*> pure y = pure ($ y) <*> u
2530		let f = move |x: i32| x.wrapping_mul(u_seed);
2531		let u = pure::<PairFirstAppliedBrand<String>, _>(<RcFnBrand as LiftFn>::new(f));
2532
2533		let lhs = apply::<RcFnBrand, PairFirstAppliedBrand<String>, _, _>(
2534			u.clone(),
2535			pure::<PairFirstAppliedBrand<String>, _>(y),
2536		);
2537
2538		let rhs_fn = <RcFnBrand as LiftFn>::new(move |f: std::rc::Rc<dyn Fn(i32) -> i32>| f(y));
2539		let rhs = apply::<RcFnBrand, PairFirstAppliedBrand<String>, _, _>(
2540			pure::<PairFirstAppliedBrand<String>, _>(rhs_fn),
2541			u,
2542		);
2543
2544		lhs == rhs
2545	}
2546
2547	// Monad Laws
2548
2549	/// Tests the left identity law for Monad.
2550	#[quickcheck]
2551	fn monad_left_identity(a: i32) -> bool {
2552		let f = |x: i32| Pair("f".to_string(), x.wrapping_mul(2));
2553		explicit::bind::<PairFirstAppliedBrand<String>, _, _, _, _>(
2554			pure::<PairFirstAppliedBrand<String>, _>(a),
2555			f,
2556		) == f(a)
2557	}
2558
2559	/// Tests the right identity law for Monad.
2560	#[quickcheck]
2561	fn monad_right_identity(
2562		first: String,
2563		second: i32,
2564	) -> bool {
2565		let m = Pair(first, second);
2566		explicit::bind::<PairFirstAppliedBrand<String>, _, _, _, _>(
2567			m.clone(),
2568			pure::<PairFirstAppliedBrand<String>, _>,
2569		) == m
2570	}
2571
2572	/// Tests the associativity law for Monad.
2573	#[quickcheck]
2574	fn monad_associativity(
2575		first: String,
2576		second: i32,
2577	) -> bool {
2578		let m = Pair(first, second);
2579		let f = |x: i32| Pair("f".to_string(), x.wrapping_mul(2));
2580		let g = |x: i32| Pair("g".to_string(), x.wrapping_add(1));
2581		explicit::bind::<PairFirstAppliedBrand<String>, _, _, _, _>(
2582			explicit::bind::<PairFirstAppliedBrand<String>, _, _, _, _>(m.clone(), f),
2583			g,
2584		) == explicit::bind::<PairFirstAppliedBrand<String>, _, _, _, _>(m, |x| {
2585			explicit::bind::<PairFirstAppliedBrand<String>, _, _, _, _>(f(x), g)
2586		})
2587	}
2588
2589	// MonadRec tests for PairFirstAppliedBrand
2590
2591	/// Tests the MonadRec identity law: `tail_rec_m(|a| pure(Done(a)), x) == pure(x)`.
2592	#[quickcheck]
2593	fn monad_rec_first_applied_identity(x: i32) -> bool {
2594		use {
2595			crate::classes::monad_rec::tail_rec_m,
2596			core::ops::ControlFlow,
2597		};
2598		tail_rec_m::<PairFirstAppliedBrand<String>, _, _>(
2599			|a| Pair(String::new(), ControlFlow::Break(a)),
2600			x,
2601		) == Pair(String::new(), x)
2602	}
2603
2604	/// Tests a recursive computation that accumulates the first value.
2605	#[test]
2606	fn monad_rec_first_applied_accumulation() {
2607		use {
2608			crate::classes::monad_rec::tail_rec_m,
2609			core::ops::ControlFlow,
2610		};
2611		let result = tail_rec_m::<PairFirstAppliedBrand<String>, _, _>(
2612			|n: i32| {
2613				if n < 3 {
2614					Pair(format!("{n},"), ControlFlow::Continue(n + 1))
2615				} else {
2616					Pair(format!("{n}"), ControlFlow::Break(n))
2617				}
2618			},
2619			0,
2620		);
2621		assert_eq!(result, Pair("0,1,2,3".to_string(), 3));
2622	}
2623
2624	/// Tests stack safety of MonadRec for PairFirstAppliedBrand.
2625	#[test]
2626	fn monad_rec_first_applied_stack_safety() {
2627		use {
2628			crate::classes::monad_rec::tail_rec_m,
2629			core::ops::ControlFlow,
2630		};
2631		let iterations: i64 = 200_000;
2632		let result = tail_rec_m::<PairFirstAppliedBrand<Vec<()>>, _, _>(
2633			|acc| {
2634				if acc < iterations {
2635					Pair(vec![], ControlFlow::Continue(acc + 1))
2636				} else {
2637					Pair(vec![], ControlFlow::Break(acc))
2638				}
2639			},
2640			0i64,
2641		);
2642		assert_eq!(result, Pair(vec![], iterations));
2643	}
2644
2645	// MonadRec tests for PairSecondAppliedBrand
2646
2647	/// Tests the MonadRec identity law: `tail_rec_m(|a| pure(Done(a)), x) == pure(x)`.
2648	#[quickcheck]
2649	fn monad_rec_second_applied_identity(x: i32) -> bool {
2650		use {
2651			crate::classes::monad_rec::tail_rec_m,
2652			core::ops::ControlFlow,
2653		};
2654		tail_rec_m::<PairSecondAppliedBrand<String>, _, _>(
2655			|a| Pair(ControlFlow::Break(a), String::new()),
2656			x,
2657		) == Pair(x, String::new())
2658	}
2659
2660	/// Tests a recursive computation that accumulates the second value.
2661	#[test]
2662	fn monad_rec_second_applied_accumulation() {
2663		use {
2664			crate::classes::monad_rec::tail_rec_m,
2665			core::ops::ControlFlow,
2666		};
2667		let result = tail_rec_m::<PairSecondAppliedBrand<String>, _, _>(
2668			|n: i32| {
2669				if n < 3 {
2670					Pair(ControlFlow::Continue(n + 1), format!("{n},"))
2671				} else {
2672					Pair(ControlFlow::Break(n), format!("{n}"))
2673				}
2674			},
2675			0,
2676		);
2677		assert_eq!(result, Pair(3, "0,1,2,3".to_string()));
2678	}
2679
2680	/// Tests stack safety of MonadRec for PairSecondAppliedBrand.
2681	#[test]
2682	fn monad_rec_second_applied_stack_safety() {
2683		use {
2684			crate::classes::monad_rec::tail_rec_m,
2685			core::ops::ControlFlow,
2686		};
2687		let iterations: i64 = 200_000;
2688		let result = tail_rec_m::<PairSecondAppliedBrand<Vec<()>>, _, _>(
2689			|acc| {
2690				if acc < iterations {
2691					Pair(ControlFlow::Continue(acc + 1), vec![])
2692				} else {
2693					Pair(ControlFlow::Break(acc), vec![])
2694				}
2695			},
2696			0i64,
2697		);
2698		assert_eq!(result, Pair(iterations, vec![]));
2699	}
2700
2701	// RefBifunctor Laws
2702
2703	/// RefBifunctor identity
2704	#[quickcheck]
2705	fn ref_bifunctor_identity(
2706		a: i32,
2707		b: i32,
2708	) -> bool {
2709		let p = Pair(a, b);
2710		explicit::bimap::<PairBrand, _, _, _, _, _, _>((|x: &i32| *x, |x: &i32| *x), &p) == p
2711	}
2712
2713	/// RefBifunctor composition
2714	#[quickcheck]
2715	fn ref_bifunctor_composition(
2716		a: i32,
2717		b: i32,
2718	) -> bool {
2719		let p = Pair(a, b);
2720		let f1 = |x: &i32| x.wrapping_add(1);
2721		let f2 = |x: &i32| x.wrapping_mul(2);
2722		let g1 = |x: &i32| x.wrapping_add(10);
2723		let g2 = |x: &i32| x.wrapping_mul(3);
2724		explicit::bimap::<PairBrand, _, _, _, _, _, _>(
2725			(|x: &i32| f2(&f1(x)), |x: &i32| g2(&g1(x))),
2726			&p,
2727		) == explicit::bimap::<PairBrand, _, _, _, _, _, _>(
2728			(f2, g2),
2729			&explicit::bimap::<PairBrand, _, _, _, _, _, _>((f1, g1), &p),
2730		)
2731	}
2732
2733	// RefBifoldable Laws
2734
2735	/// RefBifoldable fold_map correctness
2736	#[quickcheck]
2737	fn ref_bifoldable_fold_map(
2738		a: i32,
2739		b: i32,
2740	) -> bool {
2741		let p = Pair(a, b);
2742		let result = explicit::bi_fold_map::<RcFnBrand, PairBrand, _, _, _, _, _>(
2743			(|x: &i32| x.to_string(), |x: &i32| x.to_string()),
2744			&p,
2745		);
2746		result == format!("{}{}", a, b)
2747	}
2748
2749	// RefBitraversable Laws
2750
2751	/// RefBitraversable consistency
2752	#[quickcheck]
2753	fn ref_bitraversable_consistency(
2754		a: i32,
2755		b: i32,
2756	) -> bool {
2757		let p = Pair(a, b);
2758		let f = |x: &i32| Some(x.wrapping_add(1));
2759		let g = |x: &i32| Some(x.wrapping_mul(2));
2760		let traversed = explicit::bi_traverse::<RcFnBrand, PairBrand, _, _, _, _, OptionBrand, _, _>(
2761			(f, g),
2762			&p,
2763		);
2764		let mapped_then_sequenced =
2765			ref_bi_sequence::<PairBrand, RcFnBrand, _, _, OptionBrand>(&explicit::bimap::<
2766				PairBrand,
2767				_,
2768				_,
2769				_,
2770				_,
2771				_,
2772				_,
2773			>((f, g), &p));
2774		traversed == mapped_then_sequenced
2775	}
2776}