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				Applicative,
17				ApplyFirst,
18				ApplySecond,
19				Bifoldable,
20				Bifunctor,
21				Bitraversable,
22				CloneableFn,
23				Foldable,
24				Functor,
25				Lift,
26				MonadRec,
27				Monoid,
28				Pointed,
29				Semiapplicative,
30				Semigroup,
31				Semimonad,
32				Traversable,
33			},
34			impl_kind,
35			kinds::*,
36		},
37		core::ops::ControlFlow,
38		fp_macros::*,
39	};
40
41	/// Wraps two values.
42	///
43	/// A simple tuple struct that holds two values of potentially different types.
44	///
45	/// ### Higher-Kinded Type Representation
46	///
47	/// This type has multiple higher-kinded representations:
48	/// - [`PairBrand`](crate::brands::PairBrand): fully polymorphic over both values (bifunctor).
49	/// - [`PairFirstAppliedBrand<First>`](crate::brands::PairFirstAppliedBrand): the first value type is fixed, polymorphic over the second (functor over second).
50	/// - [`PairSecondAppliedBrand<Second>`](crate::brands::PairSecondAppliedBrand): the second value type is fixed, polymorphic over the first (functor over first).
51	///
52	/// ### Serialization
53	///
54	/// This type supports serialization and deserialization via [`serde`](https://serde.rs) when the `serde` feature is enabled.
55	#[document_type_parameters("The type of the first value.", "The type of the second value.")]
56	///
57	#[cfg_attr(feature = "serde", derive(serde::Serialize, serde::Deserialize))]
58	#[derive(Clone, Copy, Debug, Default, Eq, Hash, Ord, PartialEq, PartialOrd)]
59	pub struct Pair<First, Second>(
60		/// The first value.
61		pub First,
62		/// The second value.
63		pub Second,
64	);
65
66	impl_kind! {
67		for PairBrand {
68			type Of<First,Second> = Pair<First, Second>;
69		}
70	}
71
72	impl_kind! {
73		for PairBrand {
74			type Of<'a, First: 'a, Second: 'a>: 'a = Pair<First, Second>;
75		}
76	}
77
78	#[document_type_parameters("The type of the first value.", "The type of the second value.")]
79	#[document_parameters("The pair instance.")]
80	impl<First, Second> Pair<First, Second> {
81		/// Maps functions over both values in the pair.
82		///
83		/// See [`Bifunctor::bimap`] for the type class version.
84		#[document_signature]
85		///
86		#[document_type_parameters(
87			"The type of the mapped first value.",
88			"The type of the mapped second value."
89		)]
90		///
91		#[document_parameters(
92			"The function to apply to the first value.",
93			"The function to apply to the second value."
94		)]
95		///
96		#[document_returns("A new pair containing the mapped values.")]
97		///
98		#[document_examples]
99		///
100		/// ```
101		/// use fp_library::types::*;
102		///
103		/// let x = Pair(1, 5);
104		/// assert_eq!(x.bimap(|a| a + 1, |b| b * 2), Pair(2, 10));
105		/// ```
106		pub fn bimap<B, D>(
107			self,
108			f: impl FnOnce(First) -> B,
109			g: impl FnOnce(Second) -> D,
110		) -> Pair<B, D> {
111			Pair(f(self.0), g(self.1))
112		}
113
114		/// Maps a function over the first value in the pair.
115		///
116		/// See [`Bifunctor::bimap`] for the type class version.
117		#[document_signature]
118		///
119		#[document_type_parameters("The type of the mapped first value.")]
120		///
121		#[document_parameters("The function to apply to the first value.")]
122		///
123		#[document_returns("A new pair with the transformed first value.")]
124		///
125		#[document_examples]
126		///
127		/// ```
128		/// use fp_library::types::*;
129		///
130		/// let x = Pair(1, 5);
131		/// assert_eq!(x.map_first(|a| a + 1), Pair(2, 5));
132		/// ```
133		pub fn map_first<B>(
134			self,
135			f: impl FnOnce(First) -> B,
136		) -> Pair<B, Second> {
137			Pair(f(self.0), self.1)
138		}
139
140		/// Maps a function over the second value in the pair.
141		///
142		/// See [`Bifunctor::bimap`] for the type class version.
143		#[document_signature]
144		///
145		#[document_type_parameters("The type of the mapped second value.")]
146		///
147		#[document_parameters("The function to apply to the second value.")]
148		///
149		#[document_returns("A new pair with the transformed second value.")]
150		///
151		#[document_examples]
152		///
153		/// ```
154		/// use fp_library::types::*;
155		///
156		/// let x = Pair(1, 5);
157		/// assert_eq!(x.map_second(|b| b * 2), Pair(1, 10));
158		/// ```
159		pub fn map_second<D>(
160			self,
161			g: impl FnOnce(Second) -> D,
162		) -> Pair<First, D> {
163			Pair(self.0, g(self.1))
164		}
165
166		/// Folds both values into a single result.
167		///
168		/// Applies two functions to the first and second values respectively,
169		/// then combines the results using `FnOnce`.
170		#[document_signature]
171		///
172		#[document_type_parameters("The result type.")]
173		///
174		#[document_parameters(
175			"The function to apply to the first value.",
176			"The function to apply to the second value.",
177			"The function to combine the results."
178		)]
179		///
180		#[document_returns("The combined result.")]
181		///
182		#[document_examples]
183		///
184		/// ```
185		/// use fp_library::types::*;
186		///
187		/// let x = Pair(1, 2);
188		/// let y = x.fold(|a| a.to_string(), |b| b.to_string(), |a, b| format!("{a},{b}"));
189		/// assert_eq!(y, "1,2");
190		/// ```
191		pub fn fold<C>(
192			self,
193			f: impl FnOnce(First) -> C,
194			g: impl FnOnce(Second) -> C,
195			combine: impl FnOnce(C, C) -> C,
196		) -> C {
197			combine(f(self.0), g(self.1))
198		}
199
200		/// Folds the pair from right to left using two step functions.
201		///
202		/// See [`Bifoldable::bi_fold_right`] for the type class version.
203		#[document_signature]
204		///
205		#[document_type_parameters("The accumulator type.")]
206		///
207		#[document_parameters(
208			"The step function for the first value.",
209			"The step function for the second value.",
210			"The initial accumulator."
211		)]
212		///
213		#[document_returns("The result of folding: `f(first, g(second, z))`.")]
214		///
215		#[document_examples]
216		///
217		/// ```
218		/// use fp_library::types::*;
219		///
220		/// let x = Pair(3, 5);
221		/// assert_eq!(x.bi_fold_right(|a, acc| acc - a, |b, acc| acc + b, 0), 2);
222		/// ```
223		pub fn bi_fold_right<C>(
224			self,
225			f: impl FnOnce(First, C) -> C,
226			g: impl FnOnce(Second, C) -> C,
227			z: C,
228		) -> C {
229			f(self.0, g(self.1, z))
230		}
231
232		/// Folds the pair from left to right using two step functions.
233		///
234		/// See [`Bifoldable::bi_fold_left`] for the type class version.
235		#[document_signature]
236		///
237		#[document_type_parameters("The accumulator type.")]
238		///
239		#[document_parameters(
240			"The step function for the first value.",
241			"The step function for the second value.",
242			"The initial accumulator."
243		)]
244		///
245		#[document_returns("The result of folding: `g(f(z, first), second)`.")]
246		///
247		#[document_examples]
248		///
249		/// ```
250		/// use fp_library::types::*;
251		///
252		/// let x = Pair(3, 5);
253		/// assert_eq!(x.bi_fold_left(|acc, a| acc - a, |acc, b| acc + b, 0), 2);
254		/// ```
255		pub fn bi_fold_left<C>(
256			self,
257			f: impl FnOnce(C, First) -> C,
258			g: impl FnOnce(C, Second) -> C,
259			z: C,
260		) -> C {
261			g(f(z, self.0), self.1)
262		}
263
264		/// Maps both values to a monoid and combines the results.
265		///
266		/// See [`Bifoldable::bi_fold_map`] for the type class version.
267		#[document_signature]
268		///
269		#[document_type_parameters("The monoid type.")]
270		///
271		#[document_parameters(
272			"The function mapping the first value to the monoid.",
273			"The function mapping the second value to the monoid."
274		)]
275		///
276		#[document_returns("The combined monoid value.")]
277		///
278		#[document_examples]
279		///
280		/// ```
281		/// use fp_library::types::*;
282		///
283		/// let x = Pair(3, 5);
284		/// assert_eq!(x.bi_fold_map(|a: i32| a.to_string(), |b: i32| b.to_string()), "35".to_string());
285		/// ```
286		pub fn bi_fold_map<M: Semigroup>(
287			self,
288			f: impl FnOnce(First) -> M,
289			g: impl FnOnce(Second) -> M,
290		) -> M {
291			Semigroup::append(f(self.0), g(self.1))
292		}
293	}
294
295	#[document_type_parameters(
296		"The lifetime of the values.",
297		"The type of the first value.",
298		"The type of the second value."
299	)]
300	#[document_parameters("The pair instance.")]
301	impl<'a, First: 'a, Second: 'a> Pair<First, Second> {
302		/// Traverses the pair with two effectful functions.
303		///
304		/// See [`Bitraversable::bi_traverse`] for the type class version.
305		#[document_signature]
306		///
307		#[document_type_parameters(
308			"The output type for the first value.",
309			"The output type for the second value.",
310			"The applicative context."
311		)]
312		///
313		#[document_parameters(
314			"The function for the first value.",
315			"The function for the second value."
316		)]
317		///
318		#[document_returns("A pair of the transformed values wrapped in the applicative context.")]
319		///
320		#[document_examples]
321		///
322		/// ```
323		/// use fp_library::{
324		/// 	brands::*,
325		/// 	types::*,
326		/// };
327		///
328		/// let x = Pair(3, 5);
329		/// let y = x.bi_traverse::<_, _, OptionBrand>(|a| Some(a + 1), |b| Some(b * 2));
330		/// assert_eq!(y, Some(Pair(4, 10)));
331		/// ```
332		pub fn bi_traverse<C: 'a + Clone, D: 'a + Clone, F: Applicative>(
333			self,
334			f: impl Fn(First) -> Apply!(<F as Kind!( type Of<'a, T: 'a>: 'a; )>::Of<'a, C>) + 'a,
335			g: impl Fn(Second) -> Apply!(<F as Kind!( type Of<'a, T: 'a>: 'a; )>::Of<'a, D>) + 'a,
336		) -> Apply!(<F as Kind!( type Of<'a, T: 'a>: 'a; )>::Of<'a, Pair<C, D>>)
337		where
338			Pair<C, D>: Clone, {
339			F::lift2(|c, d| Pair(c, d), f(self.0), g(self.1))
340		}
341	}
342
343	#[document_type_parameters("The type of the first value.", "The type of the second value.")]
344	#[document_parameters("The pair instance.")]
345	impl<First: Semigroup, Second> Pair<First, Second> {
346		/// Chains a computation over the second value, combining first values via their semigroup.
347		///
348		/// See [`Semimonad::bind`] for the type class version
349		/// (via [`PairFirstAppliedBrand`]).
350		#[document_signature]
351		///
352		#[document_type_parameters("The type of the new second value.")]
353		///
354		#[document_parameters("The function to apply to the second value.")]
355		///
356		#[document_returns(
357			"A new pair where the first values are combined and the second value is transformed."
358		)]
359		///
360		#[document_examples]
361		///
362		/// ```
363		/// use fp_library::types::*;
364		///
365		/// assert_eq!(
366		/// 	Pair("a".to_string(), 5).bind(|x| Pair("b".to_string(), x * 2)),
367		/// 	Pair("ab".to_string(), 10)
368		/// );
369		/// ```
370		pub fn bind<C>(
371			self,
372			f: impl FnOnce(Second) -> Pair<First, C>,
373		) -> Pair<First, C> {
374			let Pair(first, second) = self;
375			let Pair(next_first, next_second) = f(second);
376			Pair(Semigroup::append(first, next_first), next_second)
377		}
378	}
379
380	#[document_type_parameters("The type of the first value.", "The type of the second value.")]
381	#[document_parameters("The pair instance.")]
382	impl<First, Second: Semigroup> Pair<First, Second> {
383		/// Chains a computation over the first value, combining second values via their semigroup.
384		///
385		/// See [`Semimonad::bind`] for the type class version
386		/// (via [`PairSecondAppliedBrand`]).
387		#[document_signature]
388		///
389		#[document_type_parameters("The type of the new first value.")]
390		///
391		#[document_parameters("The function to apply to the first value.")]
392		///
393		#[document_returns(
394			"A new pair where the first value is transformed and the second values are combined."
395		)]
396		///
397		#[document_examples]
398		///
399		/// ```
400		/// use fp_library::types::*;
401		///
402		/// assert_eq!(
403		/// 	Pair(5, "a".to_string()).bind_first(|x| Pair(x * 2, "b".to_string())),
404		/// 	Pair(10, "ab".to_string())
405		/// );
406		/// ```
407		pub fn bind_first<C>(
408			self,
409			f: impl FnOnce(First) -> Pair<C, Second>,
410		) -> Pair<C, Second> {
411			let Pair(first, second) = self;
412			let Pair(next_first, next_second) = f(first);
413			Pair(next_first, Semigroup::append(second, next_second))
414		}
415	}
416
417	impl Bifunctor for PairBrand {
418		/// Maps functions over the values in the pair.
419		///
420		/// This method applies one function to the first value and another to the second value.
421		#[document_signature]
422		///
423		#[document_type_parameters(
424			"The lifetime of the values.",
425			"The type of the first value.",
426			"The type of the mapped first value.",
427			"The type of the second value.",
428			"The type of the mapped second value."
429		)]
430		///
431		#[document_parameters(
432			"The function to apply to the first value.",
433			"The function to apply to the second value.",
434			"The pair to map over."
435		)]
436		///
437		#[document_returns("A new pair containing the mapped values.")]
438		#[document_examples]
439		///
440		/// ```
441		/// use fp_library::{
442		/// 	brands::*,
443		/// 	classes::bifunctor::*,
444		/// 	functions::*,
445		/// 	types::*,
446		/// };
447		///
448		/// let x = Pair(1, 5);
449		/// assert_eq!(bimap::<PairBrand, _, _, _, _>(|a| a + 1, |b| b * 2, x), Pair(2, 10));
450		/// ```
451		fn bimap<'a, A: 'a, B: 'a, C: 'a, D: 'a>(
452			f: impl Fn(A) -> B + 'a,
453			g: impl Fn(C) -> D + 'a,
454			p: Apply!(<Self as Kind!( type Of<'a, A: 'a, B: 'a>: 'a; )>::Of<'a, A, C>),
455		) -> Apply!(<Self as Kind!( type Of<'a, A: 'a, B: 'a>: 'a; )>::Of<'a, B, D>) {
456			p.bimap(f, g)
457		}
458	}
459
460	impl Bifoldable for PairBrand {
461		/// Folds the pair from right to left using two step functions.
462		///
463		/// Folds `Pair(a, b)` as `f(a, g(b, z))`.
464		#[document_signature]
465		///
466		#[document_type_parameters(
467			"The lifetime of the values.",
468			"The brand of the cloneable function to use.",
469			"The type of the first value.",
470			"The type of the second value.",
471			"The accumulator type."
472		)]
473		///
474		#[document_parameters(
475			"The step function for the first value.",
476			"The step function for the second value.",
477			"The initial accumulator.",
478			"The pair to fold."
479		)]
480		///
481		#[document_returns("`f(a, g(b, z))`.")]
482		#[document_examples]
483		///
484		/// ```
485		/// use fp_library::{
486		/// 	brands::*,
487		/// 	functions::*,
488		/// 	types::*,
489		/// };
490		///
491		/// let x = Pair(3, 5);
492		/// assert_eq!(
493		/// 	bi_fold_right::<RcFnBrand, PairBrand, _, _, _>(|a, acc| acc - a, |b, acc| acc + b, 0, x,),
494		/// 	2
495		/// );
496		/// ```
497		fn bi_fold_right<'a, FnBrand: CloneableFn + 'a, A: 'a + Clone, B: 'a + Clone, C: 'a>(
498			f: impl Fn(A, C) -> C + 'a,
499			g: impl Fn(B, C) -> C + 'a,
500			z: C,
501			p: Apply!(<Self as Kind!( type Of<'a, A: 'a, B: 'a>: 'a; )>::Of<'a, A, B>),
502		) -> C {
503			p.bi_fold_right(f, g, z)
504		}
505
506		/// Folds the pair from left to right using two step functions.
507		///
508		/// Folds `Pair(a, b)` as `g(f(z, a), b)`.
509		#[document_signature]
510		///
511		#[document_type_parameters(
512			"The lifetime of the values.",
513			"The brand of the cloneable function to use.",
514			"The type of the first value.",
515			"The type of the second value.",
516			"The accumulator type."
517		)]
518		///
519		#[document_parameters(
520			"The step function for the first value.",
521			"The step function for the second value.",
522			"The initial accumulator.",
523			"The pair to fold."
524		)]
525		///
526		#[document_returns("`g(f(z, a), b)`.")]
527		#[document_examples]
528		///
529		/// ```
530		/// use fp_library::{
531		/// 	brands::*,
532		/// 	functions::*,
533		/// 	types::*,
534		/// };
535		///
536		/// let x = Pair(3, 5);
537		/// assert_eq!(
538		/// 	bi_fold_left::<RcFnBrand, PairBrand, _, _, _>(|acc, a| acc - a, |acc, b| acc + b, 0, x,),
539		/// 	2
540		/// );
541		/// ```
542		fn bi_fold_left<'a, FnBrand: CloneableFn + 'a, A: 'a + Clone, B: 'a + Clone, C: 'a>(
543			f: impl Fn(C, A) -> C + 'a,
544			g: impl Fn(C, B) -> C + 'a,
545			z: C,
546			p: Apply!(<Self as Kind!( type Of<'a, A: 'a, B: 'a>: 'a; )>::Of<'a, A, B>),
547		) -> C {
548			p.bi_fold_left(f, g, z)
549		}
550
551		/// Maps both values to a monoid and combines the results.
552		///
553		/// Computes `Semigroup::append(f(a), g(b))` for `Pair(a, b)`.
554		#[document_signature]
555		///
556		#[document_type_parameters(
557			"The lifetime of the values.",
558			"The brand of the cloneable function to use.",
559			"The type of the first value.",
560			"The type of the second value.",
561			"The monoid type."
562		)]
563		///
564		#[document_parameters(
565			"The function mapping the first value to the monoid.",
566			"The function mapping the second value to the monoid.",
567			"The pair to fold."
568		)]
569		///
570		#[document_returns("`Semigroup::append(f(a), g(b))`.")]
571		#[document_examples]
572		///
573		/// ```
574		/// use fp_library::{
575		/// 	brands::*,
576		/// 	functions::*,
577		/// 	types::*,
578		/// };
579		///
580		/// assert_eq!(
581		/// 	bi_fold_map::<RcFnBrand, PairBrand, _, _, _>(
582		/// 		|a: i32| a.to_string(),
583		/// 		|b: i32| b.to_string(),
584		/// 		Pair(3, 5),
585		/// 	),
586		/// 	"35".to_string()
587		/// );
588		/// ```
589		fn bi_fold_map<'a, FnBrand: CloneableFn + 'a, A: 'a + Clone, B: 'a + Clone, M>(
590			f: impl Fn(A) -> M + 'a,
591			g: impl Fn(B) -> M + 'a,
592			p: Apply!(<Self as Kind!( type Of<'a, A: 'a, B: 'a>: 'a; )>::Of<'a, A, B>),
593		) -> M
594		where
595			M: Monoid + 'a, {
596			p.bi_fold_map(f, g)
597		}
598	}
599
600	impl Bitraversable for PairBrand {
601		/// Traverses the pair with two effectful functions.
602		///
603		/// Applies `f` to the first value and `g` to the second value,
604		/// combining the effects via `lift2`.
605		#[document_signature]
606		///
607		#[document_type_parameters(
608			"The lifetime of the values.",
609			"The type of the first value.",
610			"The type of the second value.",
611			"The output type for the first value.",
612			"The output type for the second value.",
613			"The applicative context."
614		)]
615		///
616		#[document_parameters(
617			"The function applied to the first value.",
618			"The function applied to the second value.",
619			"The pair to traverse."
620		)]
621		///
622		#[document_returns("`lift2(Pair, f(a), g(b))`.")]
623		#[document_examples]
624		///
625		/// ```
626		/// use fp_library::{
627		/// 	brands::*,
628		/// 	functions::*,
629		/// 	types::*,
630		/// };
631		///
632		/// let x = Pair(3, 5);
633		/// assert_eq!(
634		/// 	bi_traverse::<PairBrand, _, _, _, _, OptionBrand>(
635		/// 		|a: i32| Some(a + 1),
636		/// 		|b: i32| Some(b * 2),
637		/// 		x,
638		/// 	),
639		/// 	Some(Pair(4, 10))
640		/// );
641		/// ```
642		fn bi_traverse<
643			'a,
644			A: 'a + Clone,
645			B: 'a + Clone,
646			C: 'a + Clone,
647			D: 'a + Clone,
648			F: Applicative,
649		>(
650			f: impl Fn(A) -> Apply!(<F as Kind!( type Of<'a, T: 'a>: 'a; )>::Of<'a, C>) + 'a,
651			g: impl Fn(B) -> Apply!(<F as Kind!( type Of<'a, T: 'a>: 'a; )>::Of<'a, D>) + 'a,
652			p: Apply!(<Self as Kind!( type Of<'a, A: 'a, B: 'a>: 'a; )>::Of<'a, A, B>),
653		) -> 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>)>)
654		{
655			p.bi_traverse::<C, D, F>(f, g)
656		}
657	}
658
659	// PairFirstAppliedBrand<First> (Functor over Second)
660
661	impl_kind! {
662		#[document_type_parameters("The type of the first value in the pair.")]
663		impl<First: 'static> for PairFirstAppliedBrand<First> {
664			type Of<'a, A: 'a>: 'a = Pair<First, A>;
665		}
666	}
667
668	#[document_type_parameters("The type of the first value in the pair.")]
669	impl<First: 'static> Functor for PairFirstAppliedBrand<First> {
670		/// Maps a function over the second value in the pair.
671		///
672		/// 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.
673		#[document_signature]
674		///
675		#[document_type_parameters(
676			"The lifetime of the values.",
677			"The type of the second value.",
678			"The type of the result of applying the function."
679		)]
680		///
681		#[document_parameters(
682			"The function to apply to the second value.",
683			"The pair to map over."
684		)]
685		///
686		#[document_returns(
687			"A new pair containing the result of applying the function to the second value."
688		)]
689		#[document_examples]
690		///
691		/// ```
692		/// use fp_library::{
693		/// 	brands::*,
694		/// 	functions::*,
695		/// 	types::*,
696		/// };
697		///
698		/// assert_eq!(map::<PairFirstAppliedBrand<_>, _, _>(|x: i32| x * 2, Pair(1, 5)), Pair(1, 10));
699		/// ```
700		fn map<'a, A: 'a, B: 'a>(
701			func: impl Fn(A) -> B + 'a,
702			fa: Apply!(<Self as Kind!( type Of<'a, T: 'a>: 'a; )>::Of<'a, A>),
703		) -> Apply!(<Self as Kind!( type Of<'a, T: 'a>: 'a; )>::Of<'a, B>) {
704			fa.map_second(func)
705		}
706	}
707
708	#[document_type_parameters("The type of the first value in the pair.")]
709	impl<First: Clone + 'static> Lift for PairFirstAppliedBrand<First>
710	where
711		First: Semigroup,
712	{
713		/// Lifts a binary function into the pair context (over second).
714		///
715		/// 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.
716		#[document_signature]
717		///
718		#[document_type_parameters(
719			"The lifetime of the values.",
720			"The type of the first second value.",
721			"The type of the second second value.",
722			"The type of the result second value."
723		)]
724		///
725		#[document_parameters(
726			"The binary function to apply to the second values.",
727			"The first pair.",
728			"The second pair."
729		)]
730		///
731		#[document_returns(
732			"A new pair where the first values are combined using `Semigroup::append` and the second values are combined using `f`."
733		)]
734		#[document_examples]
735		///
736		/// ```
737		/// use fp_library::{
738		/// 	brands::*,
739		/// 	functions::*,
740		/// 	types::*,
741		/// };
742		///
743		/// assert_eq!(
744		/// 	lift2::<PairFirstAppliedBrand<String>, _, _, _>(
745		/// 		|x, y| x + y,
746		/// 		Pair("a".to_string(), 1),
747		/// 		Pair("b".to_string(), 2)
748		/// 	),
749		/// 	Pair("ab".to_string(), 3)
750		/// );
751		/// ```
752		fn lift2<'a, A, B, C>(
753			func: impl Fn(A, B) -> C + 'a,
754			fa: Apply!(<Self as Kind!( type Of<'a, T: 'a>: 'a; )>::Of<'a, A>),
755			fb: Apply!(<Self as Kind!( type Of<'a, T: 'a>: 'a; )>::Of<'a, B>),
756		) -> Apply!(<Self as Kind!( type Of<'a, T: 'a>: 'a; )>::Of<'a, C>)
757		where
758			A: Clone + 'a,
759			B: Clone + 'a,
760			C: 'a, {
761			let Pair(fa_first, fa_second) = fa;
762			let Pair(fb_first, fb_second) = fb;
763			Pair(Semigroup::append(fa_first, fb_first), func(fa_second, fb_second))
764		}
765	}
766
767	#[document_type_parameters("The type of the first value in the pair.")]
768	impl<First: Clone + 'static> Pointed for PairFirstAppliedBrand<First>
769	where
770		First: Monoid,
771	{
772		/// Wraps a value in a pair (with empty first).
773		///
774		/// This method wraps a value in a pair, using the `Monoid::empty()` value for the first element.
775		#[document_signature]
776		///
777		#[document_type_parameters("The lifetime of the value.", "The type of the value to wrap.")]
778		///
779		#[document_parameters("The value to wrap.")]
780		///
781		#[document_returns("A pair containing the empty value of the first type and `a`.")]
782		///
783		#[document_examples]
784		///
785		/// ```
786		/// use fp_library::{
787		/// 	brands::*,
788		/// 	functions::*,
789		/// 	types::*,
790		/// };
791		///
792		/// assert_eq!(pure::<PairFirstAppliedBrand<String>, _>(5), Pair("".to_string(), 5));
793		/// ```
794		fn pure<'a, A: 'a>(a: A) -> Apply!(<Self as Kind!( type Of<'a, T: 'a>: 'a; )>::Of<'a, A>) {
795			Pair(Monoid::empty(), a)
796		}
797	}
798
799	#[document_type_parameters("The type of the first value in the pair.")]
800	impl<First: Clone + Semigroup + 'static> ApplyFirst for PairFirstAppliedBrand<First> {}
801
802	#[document_type_parameters("The type of the first value in the pair.")]
803	impl<First: Clone + Semigroup + 'static> ApplySecond for PairFirstAppliedBrand<First> {}
804
805	#[document_type_parameters("The type of the first value in the pair.")]
806	impl<First: Clone + 'static> Semiapplicative for PairFirstAppliedBrand<First>
807	where
808		First: Semigroup,
809	{
810		/// Applies a wrapped function to a wrapped value (over second).
811		///
812		/// 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.
813		#[document_signature]
814		///
815		#[document_type_parameters(
816			"The lifetime of the values.",
817			"The brand of the cloneable function wrapper.",
818			"The type of the input value.",
819			"The type of the output value."
820		)]
821		///
822		#[document_parameters(
823			"The pair containing the function.",
824			"The pair containing the value."
825		)]
826		///
827		#[document_returns(
828			"A new pair where the first values are combined and the function is applied to the second value."
829		)]
830		#[document_examples]
831		///
832		/// ```
833		/// use fp_library::{
834		/// 	brands::*,
835		/// 	functions::*,
836		/// 	types::*,
837		/// };
838		///
839		/// let f = Pair("a".to_string(), cloneable_fn_new::<RcFnBrand, _, _>(|x: i32| x * 2));
840		/// assert_eq!(
841		/// 	apply::<RcFnBrand, PairFirstAppliedBrand<String>, _, _>(f, Pair("b".to_string(), 5)),
842		/// 	Pair("ab".to_string(), 10)
843		/// );
844		/// ```
845		fn apply<'a, FnBrand: 'a + CloneableFn, A: 'a + Clone, B: 'a>(
846			ff: Apply!(<Self as Kind!( type Of<'a, T: 'a>: 'a; )>::Of<'a, <FnBrand as CloneableFn>::Of<'a, A, B>>),
847			fa: Apply!(<Self as Kind!( type Of<'a, T: 'a>: 'a; )>::Of<'a, A>),
848		) -> Apply!(<Self as Kind!( type Of<'a, T: 'a>: 'a; )>::Of<'a, B>) {
849			Pair(Semigroup::append(ff.0, fa.0), ff.1(fa.1))
850		}
851	}
852
853	#[document_type_parameters("The type of the first value in the pair.")]
854	impl<First: Clone + 'static> Semimonad for PairFirstAppliedBrand<First>
855	where
856		First: Semigroup,
857	{
858		/// Chains pair computations (over second).
859		///
860		/// 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.
861		#[document_signature]
862		///
863		#[document_type_parameters(
864			"The lifetime of the values.",
865			"The type of the result of the first computation.",
866			"The type of the result of the second computation."
867		)]
868		///
869		#[document_parameters("The first pair.", "The function to apply to the second value.")]
870		///
871		#[document_returns("A new pair where the first values are combined.")]
872		///
873		#[document_examples]
874		///
875		/// ```
876		/// use fp_library::{
877		/// 	brands::*,
878		/// 	functions::*,
879		/// 	types::*,
880		/// };
881		///
882		/// assert_eq!(
883		/// 	bind::<PairFirstAppliedBrand<String>, _, _>(Pair("a".to_string(), 5), |x| Pair(
884		/// 		"b".to_string(),
885		/// 		x * 2
886		/// 	)),
887		/// 	Pair("ab".to_string(), 10)
888		/// );
889		/// ```
890		fn bind<'a, A: 'a, B: 'a>(
891			ma: Apply!(<Self as Kind!( type Of<'a, T: 'a>: 'a; )>::Of<'a, A>),
892			func: impl Fn(A) -> Apply!(<Self as Kind!( type Of<'a, T: 'a>: 'a; )>::Of<'a, B>) + 'a,
893		) -> Apply!(<Self as Kind!( type Of<'a, T: 'a>: 'a; )>::Of<'a, B>) {
894			ma.bind(func)
895		}
896	}
897
898	/// [`MonadRec`] implementation for [`PairFirstAppliedBrand`].
899	#[document_type_parameters("The type of the first value in the pair.")]
900	impl<First: Clone + 'static> MonadRec for PairFirstAppliedBrand<First>
901	where
902		First: Monoid,
903	{
904		/// Performs tail-recursive monadic computation over the second value, accumulating the first.
905		///
906		/// Iteratively applies the step function. Each iteration produces a pair
907		/// whose first value is combined with the running accumulator via
908		/// [`Semigroup::append`]. If the step returns `ControlFlow::Continue(a)`, the loop
909		/// continues with the new state. If it returns `ControlFlow::Break(b)`, the
910		/// computation completes with the accumulated first value and `b`.
911		#[document_signature]
912		///
913		#[document_type_parameters(
914			"The lifetime of the computation.",
915			"The type of the initial value and loop state.",
916			"The type of the result."
917		)]
918		///
919		#[document_parameters("The step function.", "The initial value.")]
920		///
921		#[document_returns("A pair with the accumulated first value and the final result.")]
922		///
923		#[document_examples]
924		///
925		/// ```
926		/// use {
927		/// 	core::ops::ControlFlow,
928		/// 	fp_library::{
929		/// 		brands::*,
930		/// 		functions::*,
931		/// 		types::*,
932		/// 	},
933		/// };
934		///
935		/// let result = tail_rec_m::<PairFirstAppliedBrand<String>, _, _>(
936		/// 	|n| {
937		/// 		if n < 3 {
938		/// 			Pair(format!("{n},"), ControlFlow::Continue(n + 1))
939		/// 		} else {
940		/// 			Pair(format!("{n}"), ControlFlow::Break(n))
941		/// 		}
942		/// 	},
943		/// 	0,
944		/// );
945		/// assert_eq!(result, Pair("0,1,2,3".to_string(), 3));
946		/// ```
947		fn tail_rec_m<'a, A: 'a, B: 'a>(
948			func: impl Fn(
949				A,
950			)
951				-> Apply!(<Self as Kind!( type Of<'a, T: 'a>: 'a; )>::Of<'a, ControlFlow<B, A>>)
952			+ 'a,
953			initial: A,
954		) -> Apply!(<Self as Kind!( type Of<'a, T: 'a>: 'a; )>::Of<'a, B>) {
955			let mut acc: First = Monoid::empty();
956			let mut current = initial;
957			loop {
958				let Pair(first, step) = func(current);
959				acc = Semigroup::append(acc, first);
960				match step {
961					ControlFlow::Continue(next) => current = next,
962					ControlFlow::Break(b) => return Pair(acc, b),
963				}
964			}
965		}
966	}
967
968	#[document_type_parameters("The type of the first value in the pair.")]
969	impl<First: 'static> Foldable for PairFirstAppliedBrand<First> {
970		/// Folds the pair from the right (over second).
971		///
972		/// This method performs a right-associative fold of the pair (over second).
973		#[document_signature]
974		///
975		#[document_type_parameters(
976			"The lifetime of the values.",
977			"The brand of the cloneable function to use.",
978			"The type of the elements in the structure.",
979			"The type of the accumulator."
980		)]
981		///
982		#[document_parameters("The folding function.", "The initial value.", "The pair to fold.")]
983		///
984		#[document_returns("`func(a, initial)`.")]
985		///
986		#[document_examples]
987		///
988		/// ```
989		/// use fp_library::{
990		/// 	brands::*,
991		/// 	functions::*,
992		/// 	types::*,
993		/// };
994		///
995		/// assert_eq!(
996		/// 	fold_right::<RcFnBrand, PairFirstAppliedBrand<()>, _, _>(|x, acc| x + acc, 0, Pair((), 5)),
997		/// 	5
998		/// );
999		/// ```
1000		fn fold_right<'a, FnBrand, A: 'a + Clone, B: 'a>(
1001			func: impl Fn(A, B) -> B + 'a,
1002			initial: B,
1003			fa: Apply!(<Self as Kind!( type Of<'a, T: 'a>: 'a; )>::Of<'a, A>),
1004		) -> B
1005		where
1006			FnBrand: CloneableFn + 'a, {
1007			func(fa.1, initial)
1008		}
1009
1010		/// Folds the pair from the left (over second).
1011		///
1012		/// This method performs a left-associative fold of the pair (over second).
1013		#[document_signature]
1014		///
1015		#[document_type_parameters(
1016			"The lifetime of the values.",
1017			"The brand of the cloneable function to use.",
1018			"The type of the elements in the structure.",
1019			"The type of the accumulator."
1020		)]
1021		///
1022		#[document_parameters(
1023			"The function to apply to the accumulator and each element.",
1024			"The initial value of the accumulator.",
1025			"The identity to fold."
1026		)]
1027		///
1028		#[document_returns("`func(initial, a)`.")]
1029		#[document_examples]
1030		///
1031		/// ```
1032		/// use fp_library::{
1033		/// 	brands::*,
1034		/// 	functions::*,
1035		/// 	types::*,
1036		/// };
1037		///
1038		/// assert_eq!(
1039		/// 	fold_left::<RcFnBrand, PairFirstAppliedBrand<()>, _, _>(|acc, x| acc + x, 0, Pair((), 5)),
1040		/// 	5
1041		/// );
1042		/// ```
1043		fn fold_left<'a, FnBrand, A: 'a + Clone, B: 'a>(
1044			func: impl Fn(B, A) -> B + 'a,
1045			initial: B,
1046			fa: Apply!(<Self as Kind!( type Of<'a, T: 'a>: 'a; )>::Of<'a, A>),
1047		) -> B
1048		where
1049			FnBrand: CloneableFn + 'a, {
1050			func(initial, fa.1)
1051		}
1052
1053		/// Maps the value to a monoid and returns it (over second).
1054		///
1055		/// This method maps the element of the pair to a monoid and then returns it (over second).
1056		#[document_signature]
1057		///
1058		#[document_type_parameters(
1059			"The lifetime of the values.",
1060			"The brand of the cloneable function to use.",
1061			"The type of the elements in the structure.",
1062			"The type of the monoid."
1063		)]
1064		///
1065		#[document_parameters("The mapping function.", "The pair to fold.")]
1066		///
1067		#[document_returns("`func(a)`.")]
1068		///
1069		#[document_examples]
1070		///
1071		/// ```
1072		/// use fp_library::{
1073		/// 	brands::*,
1074		/// 	functions::*,
1075		/// 	types::*,
1076		/// };
1077		///
1078		/// assert_eq!(
1079		/// 	fold_map::<RcFnBrand, PairFirstAppliedBrand<()>, _, _>(|x: i32| x.to_string(), Pair((), 5)),
1080		/// 	"5".to_string()
1081		/// );
1082		/// ```
1083		fn fold_map<'a, FnBrand, A: 'a + Clone, M>(
1084			func: impl Fn(A) -> M + 'a,
1085			fa: Apply!(<Self as Kind!( type Of<'a, T: 'a>: 'a; )>::Of<'a, A>),
1086		) -> M
1087		where
1088			M: Monoid + 'a,
1089			FnBrand: CloneableFn + 'a, {
1090			func(fa.1)
1091		}
1092	}
1093
1094	#[document_type_parameters("The type of the first value in the pair.")]
1095	impl<First: Clone + 'static> Traversable for PairFirstAppliedBrand<First> {
1096		/// Traverses the pair with an applicative function (over second).
1097		///
1098		/// This method maps the element of the pair to a computation, evaluates it, and combines the result into an applicative context (over second).
1099		#[document_signature]
1100		///
1101		#[document_type_parameters(
1102			"The lifetime of the values.",
1103			"The type of the elements in the traversable structure.",
1104			"The type of the elements in the resulting traversable structure.",
1105			"The applicative context."
1106		)]
1107		///
1108		#[document_parameters(
1109			"The function to apply to each element, returning a value in an applicative context.",
1110			"The pair to traverse."
1111		)]
1112		///
1113		#[document_returns("The pair wrapped in the applicative context.")]
1114		#[document_examples]
1115		///
1116		/// ```
1117		/// use fp_library::{
1118		/// 	brands::*,
1119		/// 	functions::*,
1120		/// 	types::*,
1121		/// };
1122		///
1123		/// assert_eq!(
1124		/// 	traverse::<PairFirstAppliedBrand<()>, _, _, OptionBrand>(|x| Some(x * 2), Pair((), 5)),
1125		/// 	Some(Pair((), 10))
1126		/// );
1127		/// ```
1128		fn traverse<'a, A: 'a + Clone, B: 'a + Clone, F: Applicative>(
1129			func: impl Fn(A) -> Apply!(<F as Kind!( type Of<'a, T: 'a>: 'a; )>::Of<'a, B>) + 'a,
1130			ta: Apply!(<Self as Kind!( type Of<'a, T: 'a>: 'a; )>::Of<'a, A>),
1131		) -> 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>)>)
1132		where
1133			Apply!(<Self as Kind!( type Of<'a, T: 'a>: 'a; )>::Of<'a, B>): Clone, {
1134			let Pair(first, second) = ta;
1135			F::map(move |b| Pair(first.clone(), b), func(second))
1136		}
1137
1138		/// Sequences a pair of applicative (over second).
1139		///
1140		/// This method evaluates the computation inside the pair and accumulates the result into an applicative context (over second).
1141		#[document_signature]
1142		///
1143		#[document_type_parameters(
1144			"The lifetime of the values.",
1145			"The type of the elements in the traversable structure.",
1146			"The applicative context."
1147		)]
1148		///
1149		#[document_parameters("The pair containing the applicative value.")]
1150		///
1151		#[document_returns("The pair wrapped in the applicative context.")]
1152		///
1153		#[document_examples]
1154		///
1155		/// ```
1156		/// use fp_library::{
1157		/// 	brands::*,
1158		/// 	functions::*,
1159		/// 	types::*,
1160		/// };
1161		///
1162		/// assert_eq!(
1163		/// 	sequence::<PairFirstAppliedBrand<()>, _, OptionBrand>(Pair((), Some(5))),
1164		/// 	Some(Pair((), 5))
1165		/// );
1166		/// ```
1167		fn sequence<'a, A: 'a + Clone, F: Applicative>(
1168			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>)>)
1169		) -> 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>)>)
1170		where
1171			Apply!(<F as Kind!( type Of<'a, T: 'a>: 'a; )>::Of<'a, A>): Clone,
1172			Apply!(<Self as Kind!( type Of<'a, T: 'a>: 'a; )>::Of<'a, A>): Clone, {
1173			let Pair(first, second) = ta;
1174			F::map(move |a| Pair(first.clone(), a), second)
1175		}
1176	}
1177
1178	// PairSecondAppliedBrand<Second> (Functor over First)
1179
1180	impl_kind! {
1181		#[document_type_parameters("The type of the second value in the pair.")]
1182		impl<Second: 'static> for PairSecondAppliedBrand<Second> {
1183			type Of<'a, A: 'a>: 'a = Pair<A, Second>;
1184		}
1185	}
1186
1187	#[document_type_parameters("The type of the second value in the pair.")]
1188	impl<Second: 'static> Functor for PairSecondAppliedBrand<Second> {
1189		/// Maps a function over the first value in the pair.
1190		///
1191		/// 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.
1192		#[document_signature]
1193		///
1194		#[document_type_parameters(
1195			"The lifetime of the values.",
1196			"The type of the first value.",
1197			"The type of the result of applying the function."
1198		)]
1199		///
1200		#[document_parameters("The function to apply to the first value.", "The pair to map over.")]
1201		///
1202		#[document_returns(
1203			"A new pair containing the result of applying the function to the first value."
1204		)]
1205		///
1206		#[document_examples]
1207		///
1208		/// ```
1209		/// use fp_library::{
1210		/// 	brands::*,
1211		/// 	functions::*,
1212		/// 	types::*,
1213		/// };
1214		///
1215		/// assert_eq!(map::<PairSecondAppliedBrand<_>, _, _>(|x: i32| x * 2, Pair(5, 1)), Pair(10, 1));
1216		/// ```
1217		fn map<'a, A: 'a, B: 'a>(
1218			func: impl Fn(A) -> B + 'a,
1219			fa: Apply!(<Self as Kind!( type Of<'a, T: 'a>: 'a; )>::Of<'a, A>),
1220		) -> Apply!(<Self as Kind!( type Of<'a, T: 'a>: 'a; )>::Of<'a, B>) {
1221			fa.map_first(func)
1222		}
1223	}
1224
1225	#[document_type_parameters("The type of the second value in the pair.")]
1226	impl<Second: Clone + 'static> Lift for PairSecondAppliedBrand<Second>
1227	where
1228		Second: Semigroup,
1229	{
1230		/// Lifts a binary function into the pair context (over first).
1231		///
1232		/// 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.
1233		#[document_signature]
1234		///
1235		#[document_type_parameters(
1236			"The lifetime of the values.",
1237			"The type of the first first value.",
1238			"The type of the second first value.",
1239			"The type of the result first value."
1240		)]
1241		///
1242		#[document_parameters(
1243			"The binary function to apply to the first values.",
1244			"The first pair.",
1245			"The second pair."
1246		)]
1247		///
1248		#[document_returns(
1249			"A new pair where the first values are combined using `f` and the second values are combined using `Semigroup::append`."
1250		)]
1251		#[document_examples]
1252		///
1253		/// ```
1254		/// use fp_library::{
1255		/// 	brands::*,
1256		/// 	functions::*,
1257		/// 	types::*,
1258		/// };
1259		///
1260		/// assert_eq!(
1261		/// 	lift2::<PairSecondAppliedBrand<String>, _, _, _>(
1262		/// 		|x, y| x + y,
1263		/// 		Pair(1, "a".to_string()),
1264		/// 		Pair(2, "b".to_string())
1265		/// 	),
1266		/// 	Pair(3, "ab".to_string())
1267		/// );
1268		/// ```
1269		fn lift2<'a, A, B, C>(
1270			func: impl Fn(A, B) -> C + 'a,
1271			fa: Apply!(<Self as Kind!( type Of<'a, T: 'a>: 'a; )>::Of<'a, A>),
1272			fb: Apply!(<Self as Kind!( type Of<'a, T: 'a>: 'a; )>::Of<'a, B>),
1273		) -> Apply!(<Self as Kind!( type Of<'a, T: 'a>: 'a; )>::Of<'a, C>)
1274		where
1275			A: Clone + 'a,
1276			B: Clone + 'a,
1277			C: 'a, {
1278			Pair(func(fa.0, fb.0), Semigroup::append(fa.1, fb.1))
1279		}
1280	}
1281
1282	#[document_type_parameters("The type of the second value in the pair.")]
1283	impl<Second: Clone + 'static> Pointed for PairSecondAppliedBrand<Second>
1284	where
1285		Second: Monoid,
1286	{
1287		/// Wraps a value in a pair (with empty second).
1288		///
1289		/// This method wraps a value in a pair, using the `Monoid::empty()` value for the second element.
1290		#[document_signature]
1291		///
1292		#[document_type_parameters("The lifetime of the value.", "The type of the value to wrap.")]
1293		///
1294		#[document_parameters("The value to wrap.")]
1295		///
1296		#[document_returns("A pair containing `a` and the empty value of the second type.")]
1297		///
1298		#[document_examples]
1299		///
1300		/// ```
1301		/// use fp_library::{
1302		/// 	brands::*,
1303		/// 	functions::*,
1304		/// 	types::*,
1305		/// };
1306		///
1307		/// assert_eq!(pure::<PairSecondAppliedBrand<String>, _>(5), Pair(5, "".to_string()));
1308		/// ```
1309		fn pure<'a, A: 'a>(a: A) -> Apply!(<Self as Kind!( type Of<'a, T: 'a>: 'a; )>::Of<'a, A>) {
1310			Pair(a, Monoid::empty())
1311		}
1312	}
1313
1314	#[document_type_parameters("The type of the second value in the pair.")]
1315	impl<Second: Clone + Semigroup + 'static> ApplyFirst for PairSecondAppliedBrand<Second> {}
1316
1317	#[document_type_parameters("The type of the second value in the pair.")]
1318	impl<Second: Clone + Semigroup + 'static> ApplySecond for PairSecondAppliedBrand<Second> {}
1319
1320	#[document_type_parameters("The type of the second value in the pair.")]
1321	impl<Second: Clone + 'static> Semiapplicative for PairSecondAppliedBrand<Second>
1322	where
1323		Second: Semigroup,
1324	{
1325		/// Applies a wrapped function to a wrapped value (over first).
1326		///
1327		/// This method applies a function wrapped in a result (as error) to a value wrapped in a result (as error).
1328		#[document_signature]
1329		///
1330		#[document_type_parameters(
1331			"The lifetime of the values.",
1332			"The brand of the cloneable function wrapper.",
1333			"The type of the input value.",
1334			"The type of the output value."
1335		)]
1336		///
1337		#[document_parameters(
1338			"The pair containing the function (in Err).",
1339			"The pair containing the value (in Err)."
1340		)]
1341		///
1342		#[document_returns(
1343			"`Err(f(a))` if both are `Err`, otherwise the first success encountered."
1344		)]
1345		#[document_examples]
1346		///
1347		/// ```
1348		/// use fp_library::{
1349		/// 	brands::*,
1350		/// 	functions::*,
1351		/// 	types::*,
1352		/// };
1353		///
1354		/// let f = Pair(cloneable_fn_new::<RcFnBrand, _, _>(|x: i32| x * 2), "a".to_string());
1355		/// assert_eq!(
1356		/// 	apply::<RcFnBrand, PairSecondAppliedBrand<String>, _, _>(f, Pair(5, "b".to_string())),
1357		/// 	Pair(10, "ab".to_string())
1358		/// );
1359		/// ```
1360		fn apply<'a, FnBrand: 'a + CloneableFn, A: 'a + Clone, B: 'a>(
1361			ff: Apply!(<Self as Kind!( type Of<'a, T: 'a>: 'a; )>::Of<'a, <FnBrand as CloneableFn>::Of<'a, A, B>>),
1362			fa: Apply!(<Self as Kind!( type Of<'a, T: 'a>: 'a; )>::Of<'a, A>),
1363		) -> Apply!(<Self as Kind!( type Of<'a, T: 'a>: 'a; )>::Of<'a, B>) {
1364			Pair(ff.0(fa.0), Semigroup::append(ff.1, fa.1))
1365		}
1366	}
1367
1368	#[document_type_parameters("The type of the second value in the pair.")]
1369	impl<Second: Clone + 'static> Semimonad for PairSecondAppliedBrand<Second>
1370	where
1371		Second: Semigroup,
1372	{
1373		/// Chains pair computations (over first).
1374		///
1375		/// This method chains two computations, where the second computation depends on the result of the first (over error).
1376		#[document_signature]
1377		///
1378		#[document_type_parameters(
1379			"The lifetime of the values.",
1380			"The type of the result of the first computation.",
1381			"The type of the result of the second computation."
1382		)]
1383		///
1384		#[document_parameters("The first result.", "The function to apply to the error value.")]
1385		///
1386		#[document_returns(
1387			"The result of applying `f` to the error if `ma` is `Err`, otherwise the original success."
1388		)]
1389		///
1390		#[document_examples]
1391		///
1392		/// ```
1393		/// use fp_library::{
1394		/// 	brands::*,
1395		/// 	functions::*,
1396		/// 	types::*,
1397		/// };
1398		///
1399		/// assert_eq!(
1400		/// 	bind::<PairSecondAppliedBrand<String>, _, _>(Pair(5, "a".to_string()), |x| Pair(
1401		/// 		x * 2,
1402		/// 		"b".to_string()
1403		/// 	)),
1404		/// 	Pair(10, "ab".to_string())
1405		/// );
1406		/// ```
1407		fn bind<'a, A: 'a, B: 'a>(
1408			ma: Apply!(<Self as Kind!( type Of<'a, T: 'a>: 'a; )>::Of<'a, A>),
1409			func: impl Fn(A) -> Apply!(<Self as Kind!( type Of<'a, T: 'a>: 'a; )>::Of<'a, B>) + 'a,
1410		) -> Apply!(<Self as Kind!( type Of<'a, T: 'a>: 'a; )>::Of<'a, B>) {
1411			ma.bind_first(func)
1412		}
1413	}
1414
1415	/// [`MonadRec`] implementation for [`PairSecondAppliedBrand`].
1416	#[document_type_parameters("The type of the second value in the pair.")]
1417	impl<Second: Clone + 'static> MonadRec for PairSecondAppliedBrand<Second>
1418	where
1419		Second: Monoid,
1420	{
1421		/// Performs tail-recursive monadic computation over the first value, accumulating the second.
1422		///
1423		/// Iteratively applies the step function. Each iteration produces a pair
1424		/// whose second value is combined with the running accumulator via
1425		/// [`Semigroup::append`]. If the step returns `ControlFlow::Continue(a)`, the loop
1426		/// continues with the new state. If it returns `ControlFlow::Break(b)`, the
1427		/// computation completes with `b` and the accumulated second value.
1428		#[document_signature]
1429		///
1430		#[document_type_parameters(
1431			"The lifetime of the computation.",
1432			"The type of the initial value and loop state.",
1433			"The type of the result."
1434		)]
1435		///
1436		#[document_parameters("The step function.", "The initial value.")]
1437		///
1438		#[document_returns("A pair with the final result and the accumulated second value.")]
1439		///
1440		#[document_examples]
1441		///
1442		/// ```
1443		/// use {
1444		/// 	core::ops::ControlFlow,
1445		/// 	fp_library::{
1446		/// 		brands::*,
1447		/// 		functions::*,
1448		/// 		types::*,
1449		/// 	},
1450		/// };
1451		///
1452		/// let result = tail_rec_m::<PairSecondAppliedBrand<String>, _, _>(
1453		/// 	|n| {
1454		/// 		if n < 3 {
1455		/// 			Pair(ControlFlow::Continue(n + 1), format!("{n},"))
1456		/// 		} else {
1457		/// 			Pair(ControlFlow::Break(n), format!("{n}"))
1458		/// 		}
1459		/// 	},
1460		/// 	0,
1461		/// );
1462		/// assert_eq!(result, Pair(3, "0,1,2,3".to_string()));
1463		/// ```
1464		fn tail_rec_m<'a, A: 'a, B: 'a>(
1465			func: impl Fn(
1466				A,
1467			)
1468				-> Apply!(<Self as Kind!( type Of<'a, T: 'a>: 'a; )>::Of<'a, ControlFlow<B, A>>)
1469			+ 'a,
1470			initial: A,
1471		) -> Apply!(<Self as Kind!( type Of<'a, T: 'a>: 'a; )>::Of<'a, B>) {
1472			let mut acc: Second = Monoid::empty();
1473			let mut current = initial;
1474			loop {
1475				let Pair(step, second) = func(current);
1476				acc = Semigroup::append(acc, second);
1477				match step {
1478					ControlFlow::Continue(next) => current = next,
1479					ControlFlow::Break(b) => return Pair(b, acc),
1480				}
1481			}
1482		}
1483	}
1484
1485	#[document_type_parameters("The type of the second value in the pair.")]
1486	impl<Second: 'static> Foldable for PairSecondAppliedBrand<Second> {
1487		/// Folds the pair from the right (over first).
1488		///
1489		/// This method performs a right-associative fold of the result (over error).
1490		#[document_signature]
1491		///
1492		#[document_type_parameters(
1493			"The lifetime of the values.",
1494			"The brand of the cloneable function to use.",
1495			"The type of the elements in the structure.",
1496			"The type of the accumulator."
1497		)]
1498		///
1499		#[document_parameters("The folding function.", "The initial value.", "The result to fold.")]
1500		///
1501		#[document_returns("`func(a, initial)` if `fa` is `Err(a)`, otherwise `initial`.")]
1502		///
1503		#[document_examples]
1504		///
1505		/// ```
1506		/// use fp_library::{
1507		/// 	brands::*,
1508		/// 	functions::*,
1509		/// 	types::*,
1510		/// };
1511		///
1512		/// assert_eq!(
1513		/// 	fold_right::<RcFnBrand, PairSecondAppliedBrand<()>, _, _>(|x, acc| x + acc, 0, Pair(5, ())),
1514		/// 	5
1515		/// );
1516		/// ```
1517		fn fold_right<'a, FnBrand, A: 'a + Clone, B: 'a>(
1518			func: impl Fn(A, B) -> B + 'a,
1519			initial: B,
1520			fa: Apply!(<Self as Kind!( type Of<'a, T: 'a>: 'a; )>::Of<'a, A>),
1521		) -> B
1522		where
1523			FnBrand: CloneableFn + 'a, {
1524			func(fa.0, initial)
1525		}
1526
1527		/// Folds the pair from the left (over first).
1528		///
1529		/// This method performs a left-associative fold of the result (over error).
1530		#[document_signature]
1531		///
1532		#[document_type_parameters(
1533			"The lifetime of the values.",
1534			"The brand of the cloneable function to use.",
1535			"The type of the elements in the structure.",
1536			"The type of the accumulator."
1537		)]
1538		///
1539		#[document_parameters("The folding function.", "The initial value.", "The result to fold.")]
1540		///
1541		#[document_returns("`func(initial, a)` if `fa` is `Err(a)`, otherwise `initial`.")]
1542		///
1543		#[document_examples]
1544		///
1545		/// ```
1546		/// use fp_library::{
1547		/// 	brands::*,
1548		/// 	functions::*,
1549		/// 	types::*,
1550		/// };
1551		///
1552		/// assert_eq!(
1553		/// 	fold_left::<RcFnBrand, PairSecondAppliedBrand<()>, _, _>(|acc, x| acc + x, 0, Pair(5, ())),
1554		/// 	5
1555		/// );
1556		/// ```
1557		fn fold_left<'a, FnBrand, A: 'a + Clone, B: 'a>(
1558			func: impl Fn(B, A) -> B + 'a,
1559			initial: B,
1560			fa: Apply!(<Self as Kind!( type Of<'a, T: 'a>: 'a; )>::Of<'a, A>),
1561		) -> B
1562		where
1563			FnBrand: CloneableFn + 'a, {
1564			func(initial, fa.0)
1565		}
1566
1567		/// Maps the value to a monoid and returns it (over first).
1568		///
1569		/// This method maps the element of the result to a monoid and then returns it (over error).
1570		#[document_signature]
1571		///
1572		#[document_type_parameters(
1573			"The lifetime of the values.",
1574			"The brand of the cloneable function to use.",
1575			"The type of the elements in the structure.",
1576			"The type of the monoid."
1577		)]
1578		///
1579		#[document_parameters("The mapping function.", "The result to fold.")]
1580		///
1581		#[document_returns("`func(a)` if `fa` is `Err(a)`, otherwise `M::empty()`.")]
1582		///
1583		#[document_examples]
1584		///
1585		/// ```
1586		/// use fp_library::{
1587		/// 	brands::*,
1588		/// 	functions::*,
1589		/// 	types::*,
1590		/// };
1591		///
1592		/// assert_eq!(
1593		/// 	fold_map::<RcFnBrand, PairSecondAppliedBrand<()>, _, _>(
1594		/// 		|x: i32| x.to_string(),
1595		/// 		Pair(5, ())
1596		/// 	),
1597		/// 	"5".to_string()
1598		/// );
1599		/// ```
1600		fn fold_map<'a, FnBrand, A: 'a + Clone, M>(
1601			func: impl Fn(A) -> M + 'a,
1602			fa: Apply!(<Self as Kind!( type Of<'a, T: 'a>: 'a; )>::Of<'a, A>),
1603		) -> M
1604		where
1605			M: Monoid + 'a,
1606			FnBrand: CloneableFn + 'a, {
1607			func(fa.0)
1608		}
1609	}
1610
1611	#[document_type_parameters("The type of the second value in the pair.")]
1612	impl<Second: Clone + 'static> Traversable for PairSecondAppliedBrand<Second> {
1613		/// Traverses the pair with an applicative function (over first).
1614		///
1615		/// This method maps the element of the result to a computation, evaluates it, and combines the result into an applicative context (over error).
1616		#[document_signature]
1617		///
1618		#[document_type_parameters(
1619			"The lifetime of the values.",
1620			"The type of the elements in the traversable structure.",
1621			"The type of the elements in the resulting traversable structure.",
1622			"The applicative context."
1623		)]
1624		///
1625		#[document_parameters("The function to apply.", "The result to traverse.")]
1626		///
1627		#[document_returns("The result wrapped in the applicative context.")]
1628		///
1629		#[document_examples]
1630		///
1631		/// ```
1632		/// use fp_library::{
1633		/// 	brands::*,
1634		/// 	functions::*,
1635		/// 	types::*,
1636		/// };
1637		///
1638		/// assert_eq!(
1639		/// 	traverse::<PairSecondAppliedBrand<()>, _, _, OptionBrand>(|x| Some(x * 2), Pair(5, ())),
1640		/// 	Some(Pair(10, ()))
1641		/// );
1642		/// ```
1643		fn traverse<'a, A: 'a + Clone, B: 'a + Clone, F: Applicative>(
1644			func: impl Fn(A) -> Apply!(<F as Kind!( type Of<'a, T: 'a>: 'a; )>::Of<'a, B>) + 'a,
1645			ta: Apply!(<Self as Kind!( type Of<'a, T: 'a>: 'a; )>::Of<'a, A>),
1646		) -> 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>)>)
1647		where
1648			Apply!(<Self as Kind!( type Of<'a, T: 'a>: 'a; )>::Of<'a, B>): Clone, {
1649			let Pair(first, second) = ta;
1650			F::map(move |b| Pair(b, second.clone()), func(first))
1651		}
1652
1653		/// Sequences a pair of applicative (over first).
1654		///
1655		/// This method evaluates the computation inside the result and accumulates the result into an applicative context (over error).
1656		#[document_signature]
1657		///
1658		#[document_type_parameters(
1659			"The lifetime of the values.",
1660			"The type of the elements in the traversable structure.",
1661			"The applicative context."
1662		)]
1663		///
1664		#[document_parameters("The result containing the applicative value.")]
1665		///
1666		#[document_returns("The result wrapped in the applicative context.")]
1667		///
1668		#[document_examples]
1669		///
1670		/// ```
1671		/// use fp_library::{
1672		/// 	brands::*,
1673		/// 	functions::*,
1674		/// 	types::*,
1675		/// };
1676		///
1677		/// assert_eq!(
1678		/// 	sequence::<PairSecondAppliedBrand<()>, _, OptionBrand>(Pair(Some(5), ())),
1679		/// 	Some(Pair(5, ()))
1680		/// );
1681		/// ```
1682		fn sequence<'a, A: 'a + Clone, F: Applicative>(
1683			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>)>)
1684		) -> 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>)>)
1685		where
1686			Apply!(<F as Kind!( type Of<'a, T: 'a>: 'a; )>::Of<'a, A>): Clone,
1687			Apply!(<Self as Kind!( type Of<'a, T: 'a>: 'a; )>::Of<'a, A>): Clone, {
1688			let Pair(first, second) = ta;
1689			F::map(move |a| Pair(a, second.clone()), first)
1690		}
1691	}
1692}
1693pub use inner::*;
1694
1695#[cfg(test)]
1696mod tests {
1697	use {
1698		super::inner::*,
1699		crate::{
1700			brands::*,
1701			classes::{
1702				CloneableFn,
1703				bifunctor::*,
1704			},
1705			functions::*,
1706		},
1707		quickcheck_macros::quickcheck,
1708	};
1709
1710	// Bifunctor Tests
1711
1712	/// Tests `bimap` on `Pair`.
1713	#[test]
1714	fn test_bimap() {
1715		let x = Pair(1, 5);
1716		assert_eq!(bimap::<PairBrand, _, _, _, _>(|a| a + 1, |b| b * 2, x), Pair(2, 10));
1717	}
1718
1719	// Bifunctor Laws
1720
1721	/// Tests the identity law for Bifunctor.
1722	#[quickcheck]
1723	fn bifunctor_identity(
1724		first: String,
1725		second: i32,
1726	) -> bool {
1727		let x = Pair(first, second);
1728		bimap::<PairBrand, _, _, _, _>(identity, identity, x.clone()) == x
1729	}
1730
1731	/// Tests the composition law for Bifunctor.
1732	#[quickcheck]
1733	fn bifunctor_composition(
1734		first: i32,
1735		second: i32,
1736	) -> bool {
1737		let x = Pair(first, second);
1738		let f = |x: i32| x.wrapping_add(1);
1739		let g = |x: i32| x.wrapping_mul(2);
1740		let h = |x: i32| x.wrapping_sub(1);
1741		let i = |x: i32| if x == 0 { 0 } else { x.wrapping_div(2) };
1742
1743		bimap::<PairBrand, _, _, _, _>(compose(f, g), compose(h, i), x)
1744			== bimap::<PairBrand, _, _, _, _>(f, h, bimap::<PairBrand, _, _, _, _>(g, i, x))
1745	}
1746
1747	// Functor Laws
1748
1749	/// Tests the identity law for Functor.
1750	#[quickcheck]
1751	fn functor_identity(
1752		first: String,
1753		second: i32,
1754	) -> bool {
1755		let x = Pair(first, second);
1756		map::<PairFirstAppliedBrand<String>, _, _>(identity, x.clone()) == x
1757	}
1758
1759	/// Tests the composition law for Functor.
1760	#[quickcheck]
1761	fn functor_composition(
1762		first: String,
1763		second: i32,
1764	) -> bool {
1765		let x = Pair(first, second);
1766		let f = |x: i32| x.wrapping_add(1);
1767		let g = |x: i32| x.wrapping_mul(2);
1768		map::<PairFirstAppliedBrand<String>, _, _>(compose(f, g), x.clone())
1769			== map::<PairFirstAppliedBrand<String>, _, _>(
1770				f,
1771				map::<PairFirstAppliedBrand<String>, _, _>(g, x),
1772			)
1773	}
1774
1775	// Applicative Laws
1776
1777	/// Tests the identity law for Applicative.
1778	#[quickcheck]
1779	fn applicative_identity(
1780		first: String,
1781		second: i32,
1782	) -> bool {
1783		let v = Pair(first, second);
1784		apply::<RcFnBrand, PairFirstAppliedBrand<String>, _, _>(
1785			pure::<PairFirstAppliedBrand<String>, _>(<RcFnBrand as CloneableFn>::new(identity)),
1786			v.clone(),
1787		) == v
1788	}
1789
1790	/// Tests the homomorphism law for Applicative.
1791	#[quickcheck]
1792	fn applicative_homomorphism(x: i32) -> bool {
1793		let f = |x: i32| x.wrapping_mul(2);
1794		apply::<RcFnBrand, PairFirstAppliedBrand<String>, _, _>(
1795			pure::<PairFirstAppliedBrand<String>, _>(<RcFnBrand as CloneableFn>::new(f)),
1796			pure::<PairFirstAppliedBrand<String>, _>(x),
1797		) == pure::<PairFirstAppliedBrand<String>, _>(f(x))
1798	}
1799
1800	/// Tests the composition law for Applicative.
1801	#[quickcheck]
1802	fn applicative_composition(
1803		w_first: String,
1804		w_second: i32,
1805		u_seed: i32,
1806		v_seed: i32,
1807	) -> bool {
1808		let w = Pair(w_first, w_second);
1809
1810		let u_fn = <RcFnBrand as CloneableFn>::new(move |x: i32| x.wrapping_add(u_seed));
1811		let u = pure::<PairFirstAppliedBrand<String>, _>(u_fn);
1812
1813		let v_fn = <RcFnBrand as CloneableFn>::new(move |x: i32| x.wrapping_mul(v_seed));
1814		let v = pure::<PairFirstAppliedBrand<String>, _>(v_fn);
1815
1816		// RHS: u <*> (v <*> w)
1817		let vw = apply::<RcFnBrand, PairFirstAppliedBrand<String>, _, _>(v.clone(), w.clone());
1818		let rhs = apply::<RcFnBrand, PairFirstAppliedBrand<String>, _, _>(u.clone(), vw);
1819
1820		// LHS: pure(compose) <*> u <*> v <*> w
1821		let compose_fn = <RcFnBrand as CloneableFn>::new(|f: std::rc::Rc<dyn Fn(i32) -> i32>| {
1822			let f = f.clone();
1823			<RcFnBrand as CloneableFn>::new(move |g: std::rc::Rc<dyn Fn(i32) -> i32>| {
1824				let f = f.clone();
1825				let g = g.clone();
1826				<RcFnBrand as CloneableFn>::new(move |x| f(g(x)))
1827			})
1828		});
1829
1830		let pure_compose = pure::<PairFirstAppliedBrand<String>, _>(compose_fn);
1831		let u_applied = apply::<RcFnBrand, PairFirstAppliedBrand<String>, _, _>(pure_compose, u);
1832		let uv = apply::<RcFnBrand, PairFirstAppliedBrand<String>, _, _>(u_applied, v);
1833		let lhs = apply::<RcFnBrand, PairFirstAppliedBrand<String>, _, _>(uv, w);
1834
1835		lhs == rhs
1836	}
1837
1838	/// Tests the interchange law for Applicative.
1839	#[quickcheck]
1840	fn applicative_interchange(
1841		y: i32,
1842		u_seed: i32,
1843	) -> bool {
1844		// u <*> pure y = pure ($ y) <*> u
1845		let f = move |x: i32| x.wrapping_mul(u_seed);
1846		let u = pure::<PairFirstAppliedBrand<String>, _>(<RcFnBrand as CloneableFn>::new(f));
1847
1848		let lhs = apply::<RcFnBrand, PairFirstAppliedBrand<String>, _, _>(
1849			u.clone(),
1850			pure::<PairFirstAppliedBrand<String>, _>(y),
1851		);
1852
1853		let rhs_fn =
1854			<RcFnBrand as CloneableFn>::new(move |f: std::rc::Rc<dyn Fn(i32) -> i32>| f(y));
1855		let rhs = apply::<RcFnBrand, PairFirstAppliedBrand<String>, _, _>(
1856			pure::<PairFirstAppliedBrand<String>, _>(rhs_fn),
1857			u,
1858		);
1859
1860		lhs == rhs
1861	}
1862
1863	// Monad Laws
1864
1865	/// Tests the left identity law for Monad.
1866	#[quickcheck]
1867	fn monad_left_identity(a: i32) -> bool {
1868		let f = |x: i32| Pair("f".to_string(), x.wrapping_mul(2));
1869		bind::<PairFirstAppliedBrand<String>, _, _>(pure::<PairFirstAppliedBrand<String>, _>(a), f)
1870			== f(a)
1871	}
1872
1873	/// Tests the right identity law for Monad.
1874	#[quickcheck]
1875	fn monad_right_identity(
1876		first: String,
1877		second: i32,
1878	) -> bool {
1879		let m = Pair(first, second);
1880		bind::<PairFirstAppliedBrand<String>, _, _>(
1881			m.clone(),
1882			pure::<PairFirstAppliedBrand<String>, _>,
1883		) == m
1884	}
1885
1886	/// Tests the associativity law for Monad.
1887	#[quickcheck]
1888	fn monad_associativity(
1889		first: String,
1890		second: i32,
1891	) -> bool {
1892		let m = Pair(first, second);
1893		let f = |x: i32| Pair("f".to_string(), x.wrapping_mul(2));
1894		let g = |x: i32| Pair("g".to_string(), x.wrapping_add(1));
1895		bind::<PairFirstAppliedBrand<String>, _, _>(
1896			bind::<PairFirstAppliedBrand<String>, _, _>(m.clone(), f),
1897			g,
1898		) == bind::<PairFirstAppliedBrand<String>, _, _>(m, |x| {
1899			bind::<PairFirstAppliedBrand<String>, _, _>(f(x), g)
1900		})
1901	}
1902
1903	// MonadRec tests for PairFirstAppliedBrand
1904
1905	/// Tests the MonadRec identity law: `tail_rec_m(|a| pure(Done(a)), x) == pure(x)`.
1906	#[quickcheck]
1907	fn monad_rec_first_applied_identity(x: i32) -> bool {
1908		use {
1909			crate::classes::monad_rec::tail_rec_m,
1910			core::ops::ControlFlow,
1911		};
1912		tail_rec_m::<PairFirstAppliedBrand<String>, _, _>(
1913			|a| Pair(String::new(), ControlFlow::Break(a)),
1914			x,
1915		) == Pair(String::new(), x)
1916	}
1917
1918	/// Tests a recursive computation that accumulates the first value.
1919	#[test]
1920	fn monad_rec_first_applied_accumulation() {
1921		use {
1922			crate::classes::monad_rec::tail_rec_m,
1923			core::ops::ControlFlow,
1924		};
1925		let result = tail_rec_m::<PairFirstAppliedBrand<String>, _, _>(
1926			|n: i32| {
1927				if n < 3 {
1928					Pair(format!("{n},"), ControlFlow::Continue(n + 1))
1929				} else {
1930					Pair(format!("{n}"), ControlFlow::Break(n))
1931				}
1932			},
1933			0,
1934		);
1935		assert_eq!(result, Pair("0,1,2,3".to_string(), 3));
1936	}
1937
1938	/// Tests stack safety of MonadRec for PairFirstAppliedBrand.
1939	#[test]
1940	fn monad_rec_first_applied_stack_safety() {
1941		use {
1942			crate::classes::monad_rec::tail_rec_m,
1943			core::ops::ControlFlow,
1944		};
1945		let iterations: i64 = 200_000;
1946		let result = tail_rec_m::<PairFirstAppliedBrand<Vec<()>>, _, _>(
1947			|acc| {
1948				if acc < iterations {
1949					Pair(vec![], ControlFlow::Continue(acc + 1))
1950				} else {
1951					Pair(vec![], ControlFlow::Break(acc))
1952				}
1953			},
1954			0i64,
1955		);
1956		assert_eq!(result, Pair(vec![], iterations));
1957	}
1958
1959	// MonadRec tests for PairSecondAppliedBrand
1960
1961	/// Tests the MonadRec identity law: `tail_rec_m(|a| pure(Done(a)), x) == pure(x)`.
1962	#[quickcheck]
1963	fn monad_rec_second_applied_identity(x: i32) -> bool {
1964		use {
1965			crate::classes::monad_rec::tail_rec_m,
1966			core::ops::ControlFlow,
1967		};
1968		tail_rec_m::<PairSecondAppliedBrand<String>, _, _>(
1969			|a| Pair(ControlFlow::Break(a), String::new()),
1970			x,
1971		) == Pair(x, String::new())
1972	}
1973
1974	/// Tests a recursive computation that accumulates the second value.
1975	#[test]
1976	fn monad_rec_second_applied_accumulation() {
1977		use {
1978			crate::classes::monad_rec::tail_rec_m,
1979			core::ops::ControlFlow,
1980		};
1981		let result = tail_rec_m::<PairSecondAppliedBrand<String>, _, _>(
1982			|n: i32| {
1983				if n < 3 {
1984					Pair(ControlFlow::Continue(n + 1), format!("{n},"))
1985				} else {
1986					Pair(ControlFlow::Break(n), format!("{n}"))
1987				}
1988			},
1989			0,
1990		);
1991		assert_eq!(result, Pair(3, "0,1,2,3".to_string()));
1992	}
1993
1994	/// Tests stack safety of MonadRec for PairSecondAppliedBrand.
1995	#[test]
1996	fn monad_rec_second_applied_stack_safety() {
1997		use {
1998			crate::classes::monad_rec::tail_rec_m,
1999			core::ops::ControlFlow,
2000		};
2001		let iterations: i64 = 200_000;
2002		let result = tail_rec_m::<PairSecondAppliedBrand<Vec<()>>, _, _>(
2003			|acc| {
2004				if acc < iterations {
2005					Pair(ControlFlow::Continue(acc + 1), vec![])
2006				} else {
2007					Pair(ControlFlow::Break(acc), vec![])
2008				}
2009			},
2010			0i64,
2011		);
2012		assert_eq!(result, Pair(iterations, vec![]));
2013	}
2014}