Skip to main content

fp_library/types/
tuple_2.rs

1//! Two-value tuple 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 [`Tuple2FirstAppliedBrand`](crate::brands::Tuple2FirstAppliedBrand) or second value [`Tuple2SecondAppliedBrand`](crate::brands::Tuple2SecondAppliedBrand).
4
5#[fp_macros::document_module]
6mod inner {
7	use {
8		crate::{
9			Apply,
10			brands::{
11				Tuple2Brand,
12				Tuple2FirstAppliedBrand,
13				Tuple2SecondAppliedBrand,
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	impl_kind! {
42		for Tuple2Brand {
43			type Of<First, Second> = (First, Second);
44		}
45	}
46
47	impl_kind! {
48		for Tuple2Brand {
49			type Of<'a, First: 'a, Second: 'a>: 'a = (First, Second);
50		}
51	}
52
53	impl Bifunctor for Tuple2Brand {
54		/// Maps functions over the values in the tuple.
55		///
56		/// This method applies one function to the first value and another to the second value.
57		#[document_signature]
58		///
59		#[document_type_parameters(
60			"The lifetime of the values.",
61			"The type of the first value.",
62			"The type of the mapped first value.",
63			"The type of the second value.",
64			"The type of the mapped second value."
65		)]
66		///
67		#[document_parameters(
68			"The function to apply to the first value.",
69			"The function to apply to the second value.",
70			"The tuple to map over."
71		)]
72		///
73		#[document_returns("A new tuple containing the mapped values.")]
74		#[document_examples]
75		///
76		/// ```
77		/// use fp_library::{
78		/// 	brands::*,
79		/// 	classes::bifunctor::*,
80		/// 	functions::*,
81		/// };
82		///
83		/// let x = (1, 5);
84		/// assert_eq!(bimap::<Tuple2Brand, _, _, _, _>(|a| a + 1, |b| b * 2, x), (2, 10));
85		/// ```
86		fn bimap<'a, A: 'a, B: 'a, C: 'a, D: 'a>(
87			f: impl Fn(A) -> B + 'a,
88			g: impl Fn(C) -> D + 'a,
89			p: Apply!(<Self as Kind!( type Of<'a, A: 'a, B: 'a>: 'a; )>::Of<'a, A, C>),
90		) -> Apply!(<Self as Kind!( type Of<'a, A: 'a, B: 'a>: 'a; )>::Of<'a, B, D>) {
91			(f(p.0), g(p.1))
92		}
93	}
94
95	impl Bifoldable for Tuple2Brand {
96		/// Folds a tuple using two step functions, right-associatively.
97		///
98		/// Applies `f` to the first value and `g` to the second value,
99		/// folding `(a, b)` as `f(a, g(b, z))`.
100		#[document_signature]
101		///
102		#[document_type_parameters(
103			"The lifetime of the values.",
104			"The brand of the cloneable function to use.",
105			"The type of the first element.",
106			"The type of the second element.",
107			"The accumulator type."
108		)]
109		///
110		#[document_parameters(
111			"The step function applied to the first element.",
112			"The step function applied to the second element.",
113			"The initial accumulator.",
114			"The tuple to fold."
115		)]
116		///
117		#[document_returns("`f(a, g(b, z))`.")]
118		#[document_examples]
119		///
120		/// ```
121		/// use fp_library::{
122		/// 	brands::*,
123		/// 	functions::*,
124		/// };
125		///
126		/// assert_eq!(
127		/// 	bi_fold_right::<RcFnBrand, Tuple2Brand, _, _, _>(
128		/// 		|a: i32, acc| acc - a,
129		/// 		|b: i32, acc| acc + b,
130		/// 		0,
131		/// 		(3, 5),
132		/// 	),
133		/// 	2
134		/// );
135		/// ```
136		fn bi_fold_right<'a, FnBrand: CloneableFn + 'a, A: 'a + Clone, B: 'a + Clone, C: 'a>(
137			f: impl Fn(A, C) -> C + 'a,
138			g: impl Fn(B, C) -> C + 'a,
139			z: C,
140			p: Apply!(<Self as Kind!( type Of<'a, A: 'a, B: 'a>: 'a; )>::Of<'a, A, B>),
141		) -> C {
142			let (a, b) = p;
143			f(a, g(b, z))
144		}
145
146		/// Folds a tuple using two step functions, left-associatively.
147		///
148		/// Applies `f` to the first value and `g` to the second value,
149		/// folding `(a, b)` as `g(f(z, a), b)`.
150		#[document_signature]
151		///
152		#[document_type_parameters(
153			"The lifetime of the values.",
154			"The brand of the cloneable function to use.",
155			"The type of the first element.",
156			"The type of the second element.",
157			"The accumulator type."
158		)]
159		///
160		#[document_parameters(
161			"The step function applied to the first element.",
162			"The step function applied to the second element.",
163			"The initial accumulator.",
164			"The tuple to fold."
165		)]
166		///
167		#[document_returns("`g(f(z, a), b)`.")]
168		#[document_examples]
169		///
170		/// ```
171		/// use fp_library::{
172		/// 	brands::*,
173		/// 	functions::*,
174		/// };
175		///
176		/// assert_eq!(
177		/// 	bi_fold_left::<RcFnBrand, Tuple2Brand, _, _, _>(
178		/// 		|acc, a: i32| acc - a,
179		/// 		|acc, b: i32| acc + b,
180		/// 		0,
181		/// 		(3, 5),
182		/// 	),
183		/// 	2
184		/// );
185		/// ```
186		fn bi_fold_left<'a, FnBrand: CloneableFn + 'a, A: 'a + Clone, B: 'a + Clone, C: 'a>(
187			f: impl Fn(C, A) -> C + 'a,
188			g: impl Fn(C, B) -> C + 'a,
189			z: C,
190			p: Apply!(<Self as Kind!( type Of<'a, A: 'a, B: 'a>: 'a; )>::Of<'a, A, B>),
191		) -> C {
192			let (a, b) = p;
193			g(f(z, a), b)
194		}
195
196		/// Maps both elements of a tuple to a monoid and combines the results.
197		///
198		/// Computes `M::append(f(a), g(b))` for a tuple `(a, b)`.
199		#[document_signature]
200		///
201		#[document_type_parameters(
202			"The lifetime of the values.",
203			"The brand of the cloneable function to use.",
204			"The type of the first element.",
205			"The type of the second element.",
206			"The monoid type."
207		)]
208		///
209		#[document_parameters(
210			"The function mapping the first element to the monoid.",
211			"The function mapping the second element to the monoid.",
212			"The tuple to fold."
213		)]
214		///
215		#[document_returns("`M::append(f(a), g(b))`.")]
216		#[document_examples]
217		///
218		/// ```
219		/// use fp_library::{
220		/// 	brands::*,
221		/// 	functions::*,
222		/// };
223		///
224		/// assert_eq!(
225		/// 	bi_fold_map::<RcFnBrand, Tuple2Brand, _, _, _>(
226		/// 		|a: i32| a.to_string(),
227		/// 		|b: i32| b.to_string(),
228		/// 		(3, 5),
229		/// 	),
230		/// 	"35".to_string()
231		/// );
232		/// ```
233		fn bi_fold_map<'a, FnBrand: CloneableFn + 'a, A: 'a + Clone, B: 'a + Clone, M>(
234			f: impl Fn(A) -> M + 'a,
235			g: impl Fn(B) -> M + 'a,
236			p: Apply!(<Self as Kind!( type Of<'a, A: 'a, B: 'a>: 'a; )>::Of<'a, A, B>),
237		) -> M
238		where
239			M: Monoid + 'a, {
240			let (a, b) = p;
241			M::append(f(a), g(b))
242		}
243	}
244
245	impl Bitraversable for Tuple2Brand {
246		/// Traverses a tuple with two effectful functions.
247		///
248		/// Applies `f` to the first element and `g` to the second element,
249		/// combining the effects via `lift2`.
250		#[document_signature]
251		///
252		#[document_type_parameters(
253			"The lifetime of the values.",
254			"The type of the first element.",
255			"The type of the second element.",
256			"The output type for the first element.",
257			"The output type for the second element.",
258			"The applicative context."
259		)]
260		///
261		#[document_parameters(
262			"The function applied to the first element.",
263			"The function applied to the second element.",
264			"The tuple to traverse."
265		)]
266		///
267		#[document_returns("`lift2(|c, d| (c, d), f(a), g(b))`.")]
268		#[document_examples]
269		///
270		/// ```
271		/// use fp_library::{
272		/// 	brands::*,
273		/// 	functions::*,
274		/// };
275		///
276		/// assert_eq!(
277		/// 	bi_traverse::<Tuple2Brand, _, _, _, _, OptionBrand>(
278		/// 		|a: i32| Some(a + 1),
279		/// 		|b: i32| Some(b * 2),
280		/// 		(3, 5),
281		/// 	),
282		/// 	Some((4, 10))
283		/// );
284		/// ```
285		fn bi_traverse<
286			'a,
287			A: 'a + Clone,
288			B: 'a + Clone,
289			C: 'a + Clone,
290			D: 'a + Clone,
291			F: Applicative,
292		>(
293			f: impl Fn(A) -> Apply!(<F as Kind!( type Of<'a, T: 'a>: 'a; )>::Of<'a, C>) + 'a,
294			g: impl Fn(B) -> Apply!(<F as Kind!( type Of<'a, T: 'a>: 'a; )>::Of<'a, D>) + 'a,
295			p: Apply!(<Self as Kind!( type Of<'a, A: 'a, B: 'a>: 'a; )>::Of<'a, A, B>),
296		) -> 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>)>)
297		{
298			let (a, b) = p;
299			F::lift2(|c, d| (c, d), f(a), g(b))
300		}
301	}
302
303	// Tuple2FirstAppliedBrand<First> (Functor over Second)
304
305	impl_kind! {
306		impl<First: 'static> for Tuple2FirstAppliedBrand<First> {
307			type Of<'a, A: 'a>: 'a = (First, A);
308		}
309	}
310
311	#[document_type_parameters("The type of the first value in the tuple.")]
312	impl<First: 'static> Functor for Tuple2FirstAppliedBrand<First> {
313		/// Maps a function over the second value in the tuple.
314		///
315		/// This method applies a function to the second value inside the tuple, producing a new tuple with the transformed second value. The first value remains unchanged.
316		#[document_signature]
317		///
318		#[document_type_parameters(
319			"The lifetime of the values.",
320			"The type of the second value.",
321			"The type of the result of applying the function."
322		)]
323		///
324		#[document_parameters(
325			"The function to apply to the second value.",
326			"The tuple to map over."
327		)]
328		///
329		#[document_returns(
330			"A new tuple containing the result of applying the function to the second value."
331		)]
332		#[document_examples]
333		///
334		/// ```
335		/// use fp_library::{
336		/// 	brands::*,
337		/// 	functions::*,
338		/// };
339		///
340		/// assert_eq!(map::<Tuple2FirstAppliedBrand<_>, _, _>(|x: i32| x * 2, (1, 5)), (1, 10));
341		/// ```
342		fn map<'a, A: 'a, B: 'a>(
343			func: impl Fn(A) -> B + 'a,
344			fa: Apply!(<Self as Kind!( type Of<'a, T: 'a>: 'a; )>::Of<'a, A>),
345		) -> Apply!(<Self as Kind!( type Of<'a, T: 'a>: 'a; )>::Of<'a, B>) {
346			(fa.0, func(fa.1))
347		}
348	}
349
350	#[document_type_parameters("The type of the first value in the tuple.")]
351	impl<First: Clone + 'static> Lift for Tuple2FirstAppliedBrand<First>
352	where
353		First: Semigroup,
354	{
355		/// Lifts a binary function into the tuple context (over second).
356		///
357		/// This method lifts a binary function to operate on the second values within the tuple context. The first values are combined using their `Semigroup` implementation.
358		#[document_signature]
359		///
360		#[document_type_parameters(
361			"The lifetime of the values.",
362			"The type of the first second value.",
363			"The type of the second second value.",
364			"The type of the result second value."
365		)]
366		///
367		#[document_parameters(
368			"The binary function to apply to the second values.",
369			"The first tuple.",
370			"The second tuple."
371		)]
372		///
373		#[document_returns(
374			"A new tuple where the first values are combined using `Semigroup::append` and the second values are combined using `f`."
375		)]
376		#[document_examples]
377		///
378		/// ```
379		/// use fp_library::{
380		/// 	brands::*,
381		/// 	functions::*,
382		/// };
383		///
384		/// assert_eq!(
385		/// 	lift2::<Tuple2FirstAppliedBrand<String>, _, _, _>(
386		/// 		|x, y| x + y,
387		/// 		("a".to_string(), 1),
388		/// 		("b".to_string(), 2)
389		/// 	),
390		/// 	("ab".to_string(), 3)
391		/// );
392		/// ```
393		fn lift2<'a, A, B, C>(
394			func: impl Fn(A, B) -> C + 'a,
395			fa: Apply!(<Self as Kind!( type Of<'a, T: 'a>: 'a; )>::Of<'a, A>),
396			fb: Apply!(<Self as Kind!( type Of<'a, T: 'a>: 'a; )>::Of<'a, B>),
397		) -> Apply!(<Self as Kind!( type Of<'a, T: 'a>: 'a; )>::Of<'a, C>)
398		where
399			A: Clone + 'a,
400			B: Clone + 'a,
401			C: 'a, {
402			(Semigroup::append(fa.0, fb.0), func(fa.1, fb.1))
403		}
404	}
405
406	#[document_type_parameters("The type of the first value in the tuple.")]
407	impl<First: Clone + 'static> Pointed for Tuple2FirstAppliedBrand<First>
408	where
409		First: Monoid,
410	{
411		/// Wraps a value in a tuple (with empty first).
412		///
413		/// This method wraps a value in a tuple, using the `Monoid::empty()` value for the first element.
414		#[document_signature]
415		///
416		#[document_type_parameters("The lifetime of the value.", "The type of the value to wrap.")]
417		///
418		#[document_parameters("The value to wrap.")]
419		///
420		#[document_returns("A tuple containing the empty value of the first type and `a`.")]
421		///
422		#[document_examples]
423		///
424		/// ```
425		/// use fp_library::{
426		/// 	brands::*,
427		/// 	functions::*,
428		/// };
429		///
430		/// assert_eq!(pure::<Tuple2FirstAppliedBrand<String>, _>(5), ("".to_string(), 5));
431		/// ```
432		fn pure<'a, A: 'a>(a: A) -> Apply!(<Self as Kind!( type Of<'a, T: 'a>: 'a; )>::Of<'a, A>) {
433			(Monoid::empty(), a)
434		}
435	}
436
437	#[document_type_parameters("The type of the first value in the tuple.")]
438	impl<First: Clone + Semigroup + 'static> ApplyFirst for Tuple2FirstAppliedBrand<First> {}
439	#[document_type_parameters("The type of the first value in the tuple.")]
440	impl<First: Clone + Semigroup + 'static> ApplySecond for Tuple2FirstAppliedBrand<First> {}
441
442	#[document_type_parameters("The type of the first value in the tuple.")]
443	impl<First: Clone + 'static> Semiapplicative for Tuple2FirstAppliedBrand<First>
444	where
445		First: Semigroup,
446	{
447		/// Applies a wrapped function to a wrapped value (over second).
448		///
449		/// This method applies a function wrapped in a tuple to a value wrapped in a tuple. The first values are combined using their `Semigroup` implementation.
450		#[document_signature]
451		///
452		#[document_type_parameters(
453			"The lifetime of the values.",
454			"The brand of the cloneable function wrapper.",
455			"The type of the input value.",
456			"The type of the output value."
457		)]
458		///
459		#[document_parameters(
460			"The tuple containing the function.",
461			"The tuple containing the value."
462		)]
463		///
464		#[document_returns(
465			"A new tuple where the first values are combined and the function is applied to the second value."
466		)]
467		#[document_examples]
468		///
469		/// ```
470		/// use fp_library::{
471		/// 	brands::*,
472		/// 	functions::*,
473		/// };
474		///
475		/// let f = ("a".to_string(), cloneable_fn_new::<RcFnBrand, _, _>(|x: i32| x * 2));
476		/// assert_eq!(
477		/// 	apply::<RcFnBrand, Tuple2FirstAppliedBrand<String>, _, _>(f, ("b".to_string(), 5)),
478		/// 	("ab".to_string(), 10)
479		/// );
480		/// ```
481		fn apply<'a, FnBrand: 'a + CloneableFn, A: 'a + Clone, B: 'a>(
482			ff: Apply!(<Self as Kind!( type Of<'a, T: 'a>: 'a; )>::Of<'a, <FnBrand as CloneableFn>::Of<'a, A, B>>),
483			fa: Apply!(<Self as Kind!( type Of<'a, T: 'a>: 'a; )>::Of<'a, A>),
484		) -> Apply!(<Self as Kind!( type Of<'a, T: 'a>: 'a; )>::Of<'a, B>) {
485			(Semigroup::append(ff.0, fa.0), ff.1(fa.1))
486		}
487	}
488
489	#[document_type_parameters("The type of the first value in the tuple.")]
490	impl<First: Clone + 'static> Semimonad for Tuple2FirstAppliedBrand<First>
491	where
492		First: Semigroup,
493	{
494		/// Chains tuple computations (over second).
495		///
496		/// 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.
497		#[document_signature]
498		///
499		#[document_type_parameters(
500			"The lifetime of the values.",
501			"The type of the result of the first computation.",
502			"The type of the result of the second computation."
503		)]
504		///
505		#[document_parameters("The first tuple.", "The function to apply to the second value.")]
506		///
507		#[document_returns("A new tuple where the first values are combined.")]
508		///
509		#[document_examples]
510		///
511		/// ```
512		/// use fp_library::{
513		/// 	brands::*,
514		/// 	functions::*,
515		/// };
516		///
517		/// assert_eq!(
518		/// 	bind::<Tuple2FirstAppliedBrand<String>, _, _>(("a".to_string(), 5), |x| (
519		/// 		"b".to_string(),
520		/// 		x * 2
521		/// 	)),
522		/// 	("ab".to_string(), 10)
523		/// );
524		/// ```
525		fn bind<'a, A: 'a, B: 'a>(
526			ma: Apply!(<Self as Kind!( type Of<'a, T: 'a>: 'a; )>::Of<'a, A>),
527			func: impl Fn(A) -> Apply!(<Self as Kind!( type Of<'a, T: 'a>: 'a; )>::Of<'a, B>) + 'a,
528		) -> Apply!(<Self as Kind!( type Of<'a, T: 'a>: 'a; )>::Of<'a, B>) {
529			let (first, second) = ma;
530			let (next_first, next_second) = func(second);
531			(Semigroup::append(first, next_first), next_second)
532		}
533	}
534
535	#[document_type_parameters("The type of the first value in the tuple.")]
536	impl<First: Clone + 'static> MonadRec for Tuple2FirstAppliedBrand<First>
537	where
538		First: Monoid,
539	{
540		/// Performs tail-recursive monadic computation over a tuple (varying the second element).
541		///
542		/// Iteratively applies the step function, accumulating the first element
543		/// via `Semigroup::append` at each iteration. When the step function returns
544		/// `ControlFlow::Break`, the accumulated first element and the final result are returned.
545		#[document_signature]
546		///
547		#[document_type_parameters(
548			"The lifetime of the computation.",
549			"The type of the initial value and loop state.",
550			"The type of the result."
551		)]
552		///
553		#[document_parameters("The step function.", "The initial value.")]
554		///
555		#[document_returns(
556			"A tuple with the accumulated first value and the result of the computation."
557		)]
558		///
559		#[document_examples]
560		///
561		/// ```
562		/// use {
563		/// 	core::ops::ControlFlow,
564		/// 	fp_library::{
565		/// 		brands::*,
566		/// 		functions::*,
567		/// 		types::*,
568		/// 	},
569		/// };
570		///
571		/// let result = tail_rec_m::<Tuple2FirstAppliedBrand<String>, _, _>(
572		/// 	|n| {
573		/// 		if n < 3 {
574		/// 			(format!("{n},"), ControlFlow::Continue(n + 1))
575		/// 		} else {
576		/// 			(format!("{n}"), ControlFlow::Break(n))
577		/// 		}
578		/// 	},
579		/// 	0,
580		/// );
581		/// assert_eq!(result, ("0,1,2,3".to_string(), 3));
582		/// ```
583		fn tail_rec_m<'a, A: 'a, B: 'a>(
584			func: impl Fn(
585				A,
586			)
587				-> Apply!(<Self as Kind!( type Of<'a, T: 'a>: 'a; )>::Of<'a, ControlFlow<B, A>>)
588			+ 'a,
589			initial: A,
590		) -> Apply!(<Self as Kind!( type Of<'a, T: 'a>: 'a; )>::Of<'a, B>) {
591			let mut acc: First = Monoid::empty();
592			let mut current = initial;
593			loop {
594				let (first, step) = func(current);
595				acc = Semigroup::append(acc, first);
596				match step {
597					ControlFlow::Continue(next) => current = next,
598					ControlFlow::Break(b) => return (acc, b),
599				}
600			}
601		}
602	}
603
604	#[document_type_parameters("The type of the first value in the tuple.")]
605	impl<First: 'static> Foldable for Tuple2FirstAppliedBrand<First> {
606		/// Folds the tuple from the right (over second).
607		///
608		/// This method performs a right-associative fold of the tuple (over second).
609		#[document_signature]
610		///
611		#[document_type_parameters(
612			"The lifetime of the values.",
613			"The brand of the cloneable function to use.",
614			"The type of the elements in the structure.",
615			"The type of the accumulator."
616		)]
617		///
618		#[document_parameters("The folding function.", "The initial value.", "The tuple to fold.")]
619		///
620		#[document_returns("`func(a, initial)`.")]
621		///
622		#[document_examples]
623		///
624		/// ```
625		/// use fp_library::{
626		/// 	brands::*,
627		/// 	functions::*,
628		/// };
629		///
630		/// assert_eq!(
631		/// 	fold_right::<RcFnBrand, Tuple2FirstAppliedBrand<()>, _, _>(|x, acc| x + acc, 0, ((), 5)),
632		/// 	5
633		/// );
634		/// ```
635		fn fold_right<'a, FnBrand, A: 'a + Clone, B: 'a>(
636			func: impl Fn(A, B) -> B + 'a,
637			initial: B,
638			fa: Apply!(<Self as Kind!( type Of<'a, T: 'a>: 'a; )>::Of<'a, A>),
639		) -> B
640		where
641			FnBrand: CloneableFn + 'a, {
642			func(fa.1, initial)
643		}
644
645		/// Folds the tuple from the left (over second).
646		///
647		/// This method performs a left-associative fold of the tuple (over second).
648		#[document_signature]
649		///
650		#[document_type_parameters(
651			"The lifetime of the values.",
652			"The brand of the cloneable function to use.",
653			"The type of the elements in the structure.",
654			"The type of the accumulator."
655		)]
656		///
657		#[document_parameters(
658			"The function to apply to the accumulator and each element.",
659			"The initial value of the accumulator.",
660			"The tuple to fold."
661		)]
662		///
663		#[document_returns("`func(initial, a)`.")]
664		#[document_examples]
665		///
666		/// ```
667		/// use fp_library::{
668		/// 	brands::*,
669		/// 	functions::*,
670		/// };
671		///
672		/// assert_eq!(
673		/// 	fold_left::<RcFnBrand, Tuple2FirstAppliedBrand<()>, _, _>(|acc, x| acc + x, 0, ((), 5)),
674		/// 	5
675		/// );
676		/// ```
677		fn fold_left<'a, FnBrand, A: 'a + Clone, B: 'a>(
678			func: impl Fn(B, A) -> B + 'a,
679			initial: B,
680			fa: Apply!(<Self as Kind!( type Of<'a, T: 'a>: 'a; )>::Of<'a, A>),
681		) -> B
682		where
683			FnBrand: CloneableFn + 'a, {
684			func(initial, fa.1)
685		}
686
687		/// Maps the value to a monoid and returns it (over second).
688		///
689		/// This method maps the element of the tuple to a monoid and then returns it (over second).
690		#[document_signature]
691		///
692		#[document_type_parameters(
693			"The lifetime of the values.",
694			"The brand of the cloneable function to use.",
695			"The type of the elements in the structure.",
696			"The type of the monoid."
697		)]
698		///
699		#[document_parameters("The mapping function.", "The tuple to fold.")]
700		///
701		#[document_returns("`func(a)`.")]
702		///
703		#[document_examples]
704		///
705		/// ```
706		/// use fp_library::{
707		/// 	brands::*,
708		/// 	functions::*,
709		/// };
710		///
711		/// assert_eq!(
712		/// 	fold_map::<RcFnBrand, Tuple2FirstAppliedBrand<()>, _, _>(|x: i32| x.to_string(), ((), 5)),
713		/// 	"5".to_string()
714		/// );
715		/// ```
716		fn fold_map<'a, FnBrand, A: 'a + Clone, M>(
717			func: impl Fn(A) -> M + 'a,
718			fa: Apply!(<Self as Kind!( type Of<'a, T: 'a>: 'a; )>::Of<'a, A>),
719		) -> M
720		where
721			M: Monoid + 'a,
722			FnBrand: CloneableFn + 'a, {
723			func(fa.1)
724		}
725	}
726
727	#[document_type_parameters("The type of the first value in the tuple.")]
728	impl<First: Clone + 'static> Traversable for Tuple2FirstAppliedBrand<First> {
729		/// Traverses the tuple with an applicative function (over second).
730		///
731		/// This method maps the element of the tuple to a computation, evaluates it, and combines the result into an applicative context (over second).
732		#[document_signature]
733		///
734		#[document_type_parameters(
735			"The lifetime of the values.",
736			"The type of the elements in the traversable structure.",
737			"The type of the elements in the resulting traversable structure.",
738			"The applicative context."
739		)]
740		///
741		#[document_parameters(
742			"The function to apply to each element, returning a value in an applicative context.",
743			"The tuple to traverse."
744		)]
745		///
746		#[document_returns("The tuple wrapped in the applicative context.")]
747		#[document_examples]
748		///
749		/// ```
750		/// use fp_library::{
751		/// 	brands::*,
752		/// 	functions::*,
753		/// };
754		///
755		/// assert_eq!(
756		/// 	traverse::<Tuple2FirstAppliedBrand<()>, _, _, OptionBrand>(|x| Some(x * 2), ((), 5)),
757		/// 	Some(((), 10))
758		/// );
759		/// ```
760		fn traverse<'a, A: 'a + Clone, B: 'a + Clone, F: Applicative>(
761			func: impl Fn(A) -> Apply!(<F as Kind!( type Of<'a, T: 'a>: 'a; )>::Of<'a, B>) + 'a,
762			ta: Apply!(<Self as Kind!( type Of<'a, T: 'a>: 'a; )>::Of<'a, A>),
763		) -> 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>)>)
764		where
765			Apply!(<Self as Kind!( type Of<'a, T: 'a>: 'a; )>::Of<'a, B>): Clone, {
766			let (first, second) = ta;
767			F::map(move |b| (first.clone(), b), func(second))
768		}
769
770		/// Sequences a tuple of applicative (over second).
771		///
772		/// This method evaluates the computation inside the tuple and accumulates the result into an applicative context (over second).
773		#[document_signature]
774		///
775		#[document_type_parameters(
776			"The lifetime of the values.",
777			"The type of the elements in the traversable structure.",
778			"The applicative context."
779		)]
780		///
781		#[document_parameters("The tuple containing the applicative value.")]
782		///
783		#[document_returns("The tuple wrapped in the applicative context.")]
784		///
785		#[document_examples]
786		///
787		/// ```
788		/// use fp_library::{
789		/// 	brands::*,
790		/// 	functions::*,
791		/// };
792		///
793		/// assert_eq!(
794		/// 	sequence::<Tuple2FirstAppliedBrand<()>, _, OptionBrand>(((), Some(5))),
795		/// 	Some(((), 5))
796		/// );
797		/// ```
798		fn sequence<'a, A: 'a + Clone, F: Applicative>(
799			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>)>)
800		) -> 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>)>)
801		where
802			Apply!(<F as Kind!( type Of<'a, T: 'a>: 'a; )>::Of<'a, A>): Clone,
803			Apply!(<Self as Kind!( type Of<'a, T: 'a>: 'a; )>::Of<'a, A>): Clone, {
804			let (first, second) = ta;
805			F::map(move |a| (first.clone(), a), second)
806		}
807	}
808
809	// Tuple2SecondAppliedBrand<Second> (Functor over First)
810
811	impl_kind! {
812		impl<Second: 'static> for Tuple2SecondAppliedBrand<Second> {
813			type Of<'a, A: 'a>: 'a = (A, Second);
814		}
815	}
816
817	#[document_type_parameters("The type of the second value in the tuple.")]
818	impl<Second: 'static> Functor for Tuple2SecondAppliedBrand<Second> {
819		/// Maps a function over the first value in the tuple.
820		///
821		/// This method applies a function to the first value inside the tuple, producing a new tuple with the transformed first value. The second value remains unchanged.
822		#[document_signature]
823		///
824		#[document_type_parameters(
825			"The lifetime of the values.",
826			"The type of the first value.",
827			"The type of the result of applying the function."
828		)]
829		///
830		#[document_parameters(
831			"The function to apply to the first value.",
832			"The tuple to map over."
833		)]
834		///
835		#[document_returns(
836			"A new tuple containing the result of applying the function to the first value."
837		)]
838		#[document_examples]
839		///
840		/// ```
841		/// use fp_library::{
842		/// 	brands::*,
843		/// 	functions::*,
844		/// };
845		///
846		/// assert_eq!(map::<Tuple2SecondAppliedBrand<_>, _, _>(|x: i32| x * 2, (5, 1)), (10, 1));
847		/// ```
848		fn map<'a, A: 'a, B: 'a>(
849			func: impl Fn(A) -> B + 'a,
850			fa: Apply!(<Self as Kind!( type Of<'a, T: 'a>: 'a; )>::Of<'a, A>),
851		) -> Apply!(<Self as Kind!( type Of<'a, T: 'a>: 'a; )>::Of<'a, B>) {
852			(func(fa.0), fa.1)
853		}
854	}
855
856	#[document_type_parameters("The type of the second value in the tuple.")]
857	impl<Second: Clone + 'static> Lift for Tuple2SecondAppliedBrand<Second>
858	where
859		Second: Semigroup,
860	{
861		/// Lifts a binary function into the tuple context (over first).
862		///
863		/// This method lifts a binary function to operate on the first values within the tuple context. The second values are combined using their `Semigroup` implementation.
864		#[document_signature]
865		///
866		#[document_type_parameters(
867			"The lifetime of the values.",
868			"The type of the first first value.",
869			"The type of the second first value.",
870			"The type of the result first value."
871		)]
872		///
873		#[document_parameters(
874			"The binary function to apply to the first values.",
875			"The first tuple.",
876			"The second tuple."
877		)]
878		///
879		#[document_returns(
880			"A new tuple where the first values are combined using `f` and the second values are combined using `Semigroup::append`."
881		)]
882		#[document_examples]
883		///
884		/// ```
885		/// use fp_library::{
886		/// 	brands::*,
887		/// 	functions::*,
888		/// };
889		///
890		/// assert_eq!(
891		/// 	lift2::<Tuple2SecondAppliedBrand<String>, _, _, _>(
892		/// 		|x, y| x + y,
893		/// 		(1, "a".to_string()),
894		/// 		(2, "b".to_string())
895		/// 	),
896		/// 	(3, "ab".to_string())
897		/// );
898		/// ```
899		fn lift2<'a, A, B, C>(
900			func: impl Fn(A, B) -> C + 'a,
901			fa: Apply!(<Self as Kind!( type Of<'a, T: 'a>: 'a; )>::Of<'a, A>),
902			fb: Apply!(<Self as Kind!( type Of<'a, T: 'a>: 'a; )>::Of<'a, B>),
903		) -> Apply!(<Self as Kind!( type Of<'a, T: 'a>: 'a; )>::Of<'a, C>)
904		where
905			A: Clone + 'a,
906			B: Clone + 'a,
907			C: 'a, {
908			(func(fa.0, fb.0), Semigroup::append(fa.1, fb.1))
909		}
910	}
911
912	#[document_type_parameters("The type of the second value in the tuple.")]
913	impl<Second: Clone + 'static> Pointed for Tuple2SecondAppliedBrand<Second>
914	where
915		Second: Monoid,
916	{
917		/// Wraps a value in a tuple (with empty second).
918		///
919		/// This method wraps a value in a tuple, using the `Monoid::empty()` value for the second element.
920		#[document_signature]
921		///
922		#[document_type_parameters("The lifetime of the value.", "The type of the value to wrap.")]
923		///
924		#[document_parameters("The value to wrap.")]
925		///
926		#[document_returns("A tuple containing `a` and the empty value of the second type.")]
927		///
928		#[document_examples]
929		///
930		/// ```
931		/// use fp_library::{
932		/// 	brands::*,
933		/// 	functions::*,
934		/// };
935		///
936		/// assert_eq!(pure::<Tuple2SecondAppliedBrand<String>, _>(5), (5, "".to_string()));
937		/// ```
938		fn pure<'a, A: 'a>(a: A) -> Apply!(<Self as Kind!( type Of<'a, T: 'a>: 'a; )>::Of<'a, A>) {
939			(a, Monoid::empty())
940		}
941	}
942
943	#[document_type_parameters("The type of the second value in the tuple.")]
944	impl<Second: Clone + Semigroup + 'static> ApplyFirst for Tuple2SecondAppliedBrand<Second> {}
945	#[document_type_parameters("The type of the second value in the tuple.")]
946	impl<Second: Clone + Semigroup + 'static> ApplySecond for Tuple2SecondAppliedBrand<Second> {}
947
948	#[document_type_parameters("The type of the second value in the tuple.")]
949	impl<Second: Clone + 'static> Semiapplicative for Tuple2SecondAppliedBrand<Second>
950	where
951		Second: Semigroup,
952	{
953		/// Applies a wrapped function to a wrapped value (over first).
954		///
955		/// This method applies a function wrapped in a tuple to a value wrapped in a tuple. The second values are combined using their `Semigroup` implementation.
956		#[document_signature]
957		///
958		#[document_type_parameters(
959			"The lifetime of the values.",
960			"The brand of the cloneable function wrapper.",
961			"The type of the input value.",
962			"The type of the output value."
963		)]
964		///
965		#[document_parameters(
966			"The tuple containing the function.",
967			"The tuple containing the value."
968		)]
969		///
970		#[document_returns(
971			"A new tuple where the function is applied to the first value and the second values are combined."
972		)]
973		#[document_examples]
974		///
975		/// ```
976		/// use fp_library::{
977		/// 	brands::*,
978		/// 	functions::*,
979		/// };
980		///
981		/// let f = (cloneable_fn_new::<RcFnBrand, _, _>(|x: i32| x * 2), "a".to_string());
982		/// assert_eq!(
983		/// 	apply::<RcFnBrand, Tuple2SecondAppliedBrand<String>, _, _>(f, (5, "b".to_string())),
984		/// 	(10, "ab".to_string())
985		/// );
986		/// ```
987		fn apply<'a, FnBrand: 'a + CloneableFn, A: 'a + Clone, B: 'a>(
988			ff: Apply!(<Self as Kind!( type Of<'a, T: 'a>: 'a; )>::Of<'a, <FnBrand as CloneableFn>::Of<'a, A, B>>),
989			fa: Apply!(<Self as Kind!( type Of<'a, T: 'a>: 'a; )>::Of<'a, A>),
990		) -> Apply!(<Self as Kind!( type Of<'a, T: 'a>: 'a; )>::Of<'a, B>) {
991			(ff.0(fa.0), Semigroup::append(ff.1, fa.1))
992		}
993	}
994
995	#[document_type_parameters("The type of the second value in the tuple.")]
996	impl<Second: Clone + 'static> Semimonad for Tuple2SecondAppliedBrand<Second>
997	where
998		Second: Semigroup,
999	{
1000		/// Chains tuple computations (over first).
1001		///
1002		/// This method chains two computations, where the second computation depends on the result of the first. The second values are combined using their `Semigroup` implementation.
1003		#[document_signature]
1004		///
1005		#[document_type_parameters(
1006			"The lifetime of the values.",
1007			"The type of the result of the first computation.",
1008			"The type of the result of the second computation."
1009		)]
1010		///
1011		#[document_parameters("The first tuple.", "The function to apply to the first value.")]
1012		///
1013		#[document_returns("A new tuple where the second values are combined.")]
1014		///
1015		#[document_examples]
1016		///
1017		/// ```
1018		/// use fp_library::{
1019		/// 	brands::*,
1020		/// 	functions::*,
1021		/// };
1022		///
1023		/// assert_eq!(
1024		/// 	bind::<Tuple2SecondAppliedBrand<String>, _, _>((5, "a".to_string()), |x| (
1025		/// 		x * 2,
1026		/// 		"b".to_string()
1027		/// 	)),
1028		/// 	(10, "ab".to_string())
1029		/// );
1030		/// ```
1031		fn bind<'a, A: 'a, B: 'a>(
1032			ma: Apply!(<Self as Kind!( type Of<'a, T: 'a>: 'a; )>::Of<'a, A>),
1033			func: impl Fn(A) -> Apply!(<Self as Kind!( type Of<'a, T: 'a>: 'a; )>::Of<'a, B>) + 'a,
1034		) -> Apply!(<Self as Kind!( type Of<'a, T: 'a>: 'a; )>::Of<'a, B>) {
1035			let (first, second) = ma;
1036			let (next_first, next_second) = func(first);
1037			(next_first, Semigroup::append(second, next_second))
1038		}
1039	}
1040
1041	#[document_type_parameters("The type of the second value in the tuple.")]
1042	impl<Second: Clone + 'static> MonadRec for Tuple2SecondAppliedBrand<Second>
1043	where
1044		Second: Monoid,
1045	{
1046		/// Performs tail-recursive monadic computation over a tuple (varying the first element).
1047		///
1048		/// Iteratively applies the step function, accumulating the second element
1049		/// via `Semigroup::append` at each iteration. When the step function returns
1050		/// `ControlFlow::Break`, the final result and the accumulated second element are returned.
1051		#[document_signature]
1052		///
1053		#[document_type_parameters(
1054			"The lifetime of the computation.",
1055			"The type of the initial value and loop state.",
1056			"The type of the result."
1057		)]
1058		///
1059		#[document_parameters("The step function.", "The initial value.")]
1060		///
1061		#[document_returns(
1062			"A tuple with the result of the computation and the accumulated second value."
1063		)]
1064		///
1065		#[document_examples]
1066		///
1067		/// ```
1068		/// use {
1069		/// 	core::ops::ControlFlow,
1070		/// 	fp_library::{
1071		/// 		brands::*,
1072		/// 		functions::*,
1073		/// 		types::*,
1074		/// 	},
1075		/// };
1076		///
1077		/// let result = tail_rec_m::<Tuple2SecondAppliedBrand<String>, _, _>(
1078		/// 	|n| {
1079		/// 		if n < 3 {
1080		/// 			(ControlFlow::Continue(n + 1), format!("{n},"))
1081		/// 		} else {
1082		/// 			(ControlFlow::Break(n), format!("{n}"))
1083		/// 		}
1084		/// 	},
1085		/// 	0,
1086		/// );
1087		/// assert_eq!(result, (3, "0,1,2,3".to_string()));
1088		/// ```
1089		fn tail_rec_m<'a, A: 'a, B: 'a>(
1090			func: impl Fn(
1091				A,
1092			)
1093				-> Apply!(<Self as Kind!( type Of<'a, T: 'a>: 'a; )>::Of<'a, ControlFlow<B, A>>)
1094			+ 'a,
1095			initial: A,
1096		) -> Apply!(<Self as Kind!( type Of<'a, T: 'a>: 'a; )>::Of<'a, B>) {
1097			let mut acc: Second = Monoid::empty();
1098			let mut current = initial;
1099			loop {
1100				let (step, second) = func(current);
1101				acc = Semigroup::append(acc, second);
1102				match step {
1103					ControlFlow::Continue(next) => current = next,
1104					ControlFlow::Break(b) => return (b, acc),
1105				}
1106			}
1107		}
1108	}
1109
1110	#[document_type_parameters("The type of the second value in the tuple.")]
1111	impl<Second: 'static> Foldable for Tuple2SecondAppliedBrand<Second> {
1112		/// Folds the tuple from the right (over first).
1113		///
1114		/// This method performs a right-associative fold of the tuple (over first).
1115		#[document_signature]
1116		///
1117		#[document_type_parameters(
1118			"The lifetime of the values.",
1119			"The brand of the cloneable function to use.",
1120			"The type of the elements in the structure.",
1121			"The type of the accumulator."
1122		)]
1123		///
1124		#[document_parameters("The folding function.", "The initial value.", "The tuple to fold.")]
1125		///
1126		#[document_returns("`func(a, initial)`.")]
1127		///
1128		#[document_examples]
1129		///
1130		/// ```
1131		/// use fp_library::{
1132		/// 	brands::*,
1133		/// 	functions::*,
1134		/// };
1135		///
1136		/// assert_eq!(
1137		/// 	fold_right::<RcFnBrand, Tuple2SecondAppliedBrand<()>, _, _>(|x, acc| x + acc, 0, (5, ())),
1138		/// 	5
1139		/// );
1140		/// ```
1141		fn fold_right<'a, FnBrand, A: 'a + Clone, B: 'a>(
1142			func: impl Fn(A, B) -> B + 'a,
1143			initial: B,
1144			fa: Apply!(<Self as Kind!( type Of<'a, T: 'a>: 'a; )>::Of<'a, A>),
1145		) -> B
1146		where
1147			FnBrand: CloneableFn + 'a, {
1148			func(fa.0, initial)
1149		}
1150
1151		/// Folds the tuple from the left (over first).
1152		///
1153		/// This method performs a left-associative fold of the tuple (over first).
1154		#[document_signature]
1155		///
1156		#[document_type_parameters(
1157			"The lifetime of the values.",
1158			"The brand of the cloneable function to use.",
1159			"The type of the elements in the structure.",
1160			"The type of the accumulator."
1161		)]
1162		///
1163		#[document_parameters("The folding function.", "The initial value.", "The tuple to fold.")]
1164		///
1165		#[document_returns("`func(initial, a)`.")]
1166		///
1167		#[document_examples]
1168		///
1169		/// ```
1170		/// use fp_library::{
1171		/// 	brands::*,
1172		/// 	functions::*,
1173		/// };
1174		///
1175		/// assert_eq!(
1176		/// 	fold_left::<RcFnBrand, Tuple2SecondAppliedBrand<()>, _, _>(|acc, x| acc + x, 0, (5, ())),
1177		/// 	5
1178		/// );
1179		/// ```
1180		fn fold_left<'a, FnBrand, A: 'a + Clone, B: 'a>(
1181			func: impl Fn(B, A) -> B + 'a,
1182			initial: B,
1183			fa: Apply!(<Self as Kind!( type Of<'a, T: 'a>: 'a; )>::Of<'a, A>),
1184		) -> B
1185		where
1186			FnBrand: CloneableFn + 'a, {
1187			func(initial, fa.0)
1188		}
1189
1190		/// Maps the value to a monoid and returns it (over first).
1191		///
1192		/// This method maps the element of the tuple to a monoid and then returns it (over first).
1193		#[document_signature]
1194		///
1195		#[document_type_parameters(
1196			"The lifetime of the values.",
1197			"The brand of the cloneable function to use.",
1198			"The type of the elements in the structure.",
1199			"The type of the monoid."
1200		)]
1201		///
1202		#[document_parameters("The mapping function.", "The tuple to fold.")]
1203		///
1204		#[document_returns("`func(a)`.")]
1205		///
1206		#[document_examples]
1207		///
1208		/// ```
1209		/// use fp_library::{
1210		/// 	brands::*,
1211		/// 	functions::*,
1212		/// };
1213		///
1214		/// assert_eq!(
1215		/// 	fold_map::<RcFnBrand, Tuple2SecondAppliedBrand<()>, _, _>(|x: i32| x.to_string(), (5, ())),
1216		/// 	"5".to_string()
1217		/// );
1218		/// ```
1219		fn fold_map<'a, FnBrand, A: 'a + Clone, M>(
1220			func: impl Fn(A) -> M + 'a,
1221			fa: Apply!(<Self as Kind!( type Of<'a, T: 'a>: 'a; )>::Of<'a, A>),
1222		) -> M
1223		where
1224			M: Monoid + 'a,
1225			FnBrand: CloneableFn + 'a, {
1226			func(fa.0)
1227		}
1228	}
1229
1230	#[document_type_parameters("The type of the second value in the tuple.")]
1231	impl<Second: Clone + 'static> Traversable for Tuple2SecondAppliedBrand<Second> {
1232		/// Traverses the tuple with an applicative function (over first).
1233		///
1234		/// This method maps the element of the tuple to a computation, evaluates it, and combines the result into an applicative context (over first).
1235		#[document_signature]
1236		///
1237		#[document_type_parameters(
1238			"The lifetime of the values.",
1239			"The type of the elements in the traversable structure.",
1240			"The type of the elements in the resulting traversable structure.",
1241			"The applicative context."
1242		)]
1243		///
1244		#[document_parameters("The function to apply.", "The tuple to traverse.")]
1245		///
1246		#[document_returns("The tuple wrapped in the applicative context.")]
1247		///
1248		#[document_examples]
1249		///
1250		/// ```
1251		/// use fp_library::{
1252		/// 	brands::*,
1253		/// 	functions::*,
1254		/// };
1255		///
1256		/// assert_eq!(
1257		/// 	traverse::<Tuple2SecondAppliedBrand<()>, _, _, OptionBrand>(|x| Some(x * 2), (5, ())),
1258		/// 	Some((10, ()))
1259		/// );
1260		/// ```
1261		fn traverse<'a, A: 'a + Clone, B: 'a + Clone, F: Applicative>(
1262			func: impl Fn(A) -> Apply!(<F as Kind!( type Of<'a, T: 'a>: 'a; )>::Of<'a, B>) + 'a,
1263			ta: Apply!(<Self as Kind!( type Of<'a, T: 'a>: 'a; )>::Of<'a, A>),
1264		) -> 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>)>)
1265		where
1266			Apply!(<Self as Kind!( type Of<'a, T: 'a>: 'a; )>::Of<'a, B>): Clone, {
1267			let (first, second) = ta;
1268			F::map(move |b| (b, second.clone()), func(first))
1269		}
1270
1271		/// Sequences a tuple of applicative (over first).
1272		///
1273		/// This method evaluates the computation inside the tuple and accumulates the result into an applicative context (over first).
1274		#[document_signature]
1275		///
1276		#[document_type_parameters(
1277			"The lifetime of the values.",
1278			"The type of the elements in the traversable structure.",
1279			"The applicative context."
1280		)]
1281		///
1282		#[document_parameters("The tuple containing the applicative value.")]
1283		///
1284		#[document_returns("The tuple wrapped in the applicative context.")]
1285		///
1286		#[document_examples]
1287		///
1288		/// ```
1289		/// use fp_library::{
1290		/// 	brands::*,
1291		/// 	functions::*,
1292		/// };
1293		///
1294		/// assert_eq!(
1295		/// 	sequence::<Tuple2SecondAppliedBrand<()>, _, OptionBrand>((Some(5), ())),
1296		/// 	Some((5, ()))
1297		/// );
1298		/// ```
1299		fn sequence<'a, A: 'a + Clone, F: Applicative>(
1300			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>)>)
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, A>)>)
1302		where
1303			Apply!(<F as Kind!( type Of<'a, T: 'a>: 'a; )>::Of<'a, A>): Clone,
1304			Apply!(<Self as Kind!( type Of<'a, T: 'a>: 'a; )>::Of<'a, A>): Clone, {
1305			let (first, second) = ta;
1306			F::map(move |a| (a, second.clone()), first)
1307		}
1308	}
1309}
1310
1311#[cfg(test)]
1312mod tests {
1313
1314	use {
1315		crate::{
1316			brands::*,
1317			classes::{
1318				CloneableFn,
1319				bifunctor::*,
1320				monad_rec::tail_rec_m,
1321			},
1322			functions::*,
1323		},
1324		core::ops::ControlFlow,
1325		quickcheck_macros::quickcheck,
1326	};
1327
1328	// Bifunctor Tests
1329
1330	/// Tests `bimap` on `Tuple2`.
1331	#[test]
1332	fn test_bimap() {
1333		let x = (1, 5);
1334		assert_eq!(bimap::<Tuple2Brand, _, _, _, _>(|a| a + 1, |b| b * 2, x), (2, 10));
1335	}
1336
1337	// Bifunctor Laws
1338
1339	/// Tests the identity law for Bifunctor.
1340	#[quickcheck]
1341	fn bifunctor_identity(
1342		first: String,
1343		second: i32,
1344	) -> bool {
1345		let x = (first, second);
1346		bimap::<Tuple2Brand, _, _, _, _>(identity, identity, x.clone()) == x
1347	}
1348
1349	/// Tests the composition law for Bifunctor.
1350	#[quickcheck]
1351	fn bifunctor_composition(
1352		first: i32,
1353		second: i32,
1354	) -> bool {
1355		let x = (first, second);
1356		let f = |x: i32| x.wrapping_add(1);
1357		let g = |x: i32| x.wrapping_mul(2);
1358		let h = |x: i32| x.wrapping_sub(1);
1359		let i = |x: i32| if x == 0 { 0 } else { x.wrapping_div(2) };
1360
1361		bimap::<Tuple2Brand, _, _, _, _>(compose(f, g), compose(h, i), x)
1362			== bimap::<Tuple2Brand, _, _, _, _>(f, h, bimap::<Tuple2Brand, _, _, _, _>(g, i, x))
1363	}
1364
1365	// Functor Laws
1366
1367	/// Tests the identity law for Functor.
1368	#[quickcheck]
1369	fn functor_identity(
1370		first: String,
1371		second: i32,
1372	) -> bool {
1373		let x = (first, second);
1374		map::<Tuple2FirstAppliedBrand<String>, _, _>(identity, x.clone()) == x
1375	}
1376
1377	/// Tests the composition law for Functor.
1378	#[quickcheck]
1379	fn functor_composition(
1380		first: String,
1381		second: i32,
1382	) -> bool {
1383		let x = (first, second);
1384		let f = |x: i32| x.wrapping_add(1);
1385		let g = |x: i32| x.wrapping_mul(2);
1386		map::<Tuple2FirstAppliedBrand<String>, _, _>(compose(f, g), x.clone())
1387			== map::<Tuple2FirstAppliedBrand<String>, _, _>(
1388				f,
1389				map::<Tuple2FirstAppliedBrand<String>, _, _>(g, x),
1390			)
1391	}
1392
1393	// Applicative Laws
1394
1395	/// Tests the identity law for Applicative.
1396	#[quickcheck]
1397	fn applicative_identity(
1398		first: String,
1399		second: i32,
1400	) -> bool {
1401		let v = (first, second);
1402		apply::<RcFnBrand, Tuple2FirstAppliedBrand<String>, _, _>(
1403			pure::<Tuple2FirstAppliedBrand<String>, _>(<RcFnBrand as CloneableFn>::new(identity)),
1404			v.clone(),
1405		) == v
1406	}
1407
1408	/// Tests the homomorphism law for Applicative.
1409	#[quickcheck]
1410	fn applicative_homomorphism(x: i32) -> bool {
1411		let f = |x: i32| x.wrapping_mul(2);
1412		apply::<RcFnBrand, Tuple2FirstAppliedBrand<String>, _, _>(
1413			pure::<Tuple2FirstAppliedBrand<String>, _>(<RcFnBrand as CloneableFn>::new(f)),
1414			pure::<Tuple2FirstAppliedBrand<String>, _>(x),
1415		) == pure::<Tuple2FirstAppliedBrand<String>, _>(f(x))
1416	}
1417
1418	/// Tests the composition law for Applicative.
1419	#[quickcheck]
1420	fn applicative_composition(
1421		w_first: String,
1422		w_second: i32,
1423		u_seed: i32,
1424		v_seed: i32,
1425	) -> bool {
1426		let w = (w_first, w_second);
1427
1428		let u_fn = <RcFnBrand as CloneableFn>::new(move |x: i32| x.wrapping_add(u_seed));
1429		let u = pure::<Tuple2FirstAppliedBrand<String>, _>(u_fn);
1430
1431		let v_fn = <RcFnBrand as CloneableFn>::new(move |x: i32| x.wrapping_mul(v_seed));
1432		let v = pure::<Tuple2FirstAppliedBrand<String>, _>(v_fn);
1433
1434		// RHS: u <*> (v <*> w)
1435		let vw = apply::<RcFnBrand, Tuple2FirstAppliedBrand<String>, _, _>(v.clone(), w.clone());
1436		let rhs = apply::<RcFnBrand, Tuple2FirstAppliedBrand<String>, _, _>(u.clone(), vw);
1437
1438		// LHS: pure(compose) <*> u <*> v <*> w
1439		let compose_fn = <RcFnBrand as CloneableFn>::new(|f: std::rc::Rc<dyn Fn(i32) -> i32>| {
1440			let f = f.clone();
1441			<RcFnBrand as CloneableFn>::new(move |g: std::rc::Rc<dyn Fn(i32) -> i32>| {
1442				let f = f.clone();
1443				let g = g.clone();
1444				<RcFnBrand as CloneableFn>::new(move |x| f(g(x)))
1445			})
1446		});
1447
1448		let pure_compose = pure::<Tuple2FirstAppliedBrand<String>, _>(compose_fn);
1449		let u_applied = apply::<RcFnBrand, Tuple2FirstAppliedBrand<String>, _, _>(pure_compose, u);
1450		let uv = apply::<RcFnBrand, Tuple2FirstAppliedBrand<String>, _, _>(u_applied, v);
1451		let lhs = apply::<RcFnBrand, Tuple2FirstAppliedBrand<String>, _, _>(uv, w);
1452
1453		lhs == rhs
1454	}
1455
1456	/// Tests the interchange law for Applicative.
1457	#[quickcheck]
1458	fn applicative_interchange(
1459		y: i32,
1460		u_seed: i32,
1461	) -> bool {
1462		// u <*> pure y = pure ($ y) <*> u
1463		let f = move |x: i32| x.wrapping_mul(u_seed);
1464		let u = pure::<Tuple2FirstAppliedBrand<String>, _>(<RcFnBrand as CloneableFn>::new(f));
1465
1466		let lhs = apply::<RcFnBrand, Tuple2FirstAppliedBrand<String>, _, _>(
1467			u.clone(),
1468			pure::<Tuple2FirstAppliedBrand<String>, _>(y),
1469		);
1470
1471		let rhs_fn =
1472			<RcFnBrand as CloneableFn>::new(move |f: std::rc::Rc<dyn Fn(i32) -> i32>| f(y));
1473		let rhs = apply::<RcFnBrand, Tuple2FirstAppliedBrand<String>, _, _>(
1474			pure::<Tuple2FirstAppliedBrand<String>, _>(rhs_fn),
1475			u,
1476		);
1477
1478		lhs == rhs
1479	}
1480
1481	// Monad Laws
1482
1483	/// Tests the left identity law for Monad.
1484	#[quickcheck]
1485	fn monad_left_identity(a: i32) -> bool {
1486		let f = |x: i32| ("f".to_string(), x.wrapping_mul(2));
1487		bind::<Tuple2FirstAppliedBrand<String>, _, _>(
1488			pure::<Tuple2FirstAppliedBrand<String>, _>(a),
1489			f,
1490		) == f(a)
1491	}
1492
1493	/// Tests the right identity law for Monad.
1494	#[quickcheck]
1495	fn monad_right_identity(
1496		first: String,
1497		second: i32,
1498	) -> bool {
1499		let m = (first, second);
1500		bind::<Tuple2FirstAppliedBrand<String>, _, _>(
1501			m.clone(),
1502			pure::<Tuple2FirstAppliedBrand<String>, _>,
1503		) == m
1504	}
1505
1506	/// Tests the associativity law for Monad.
1507	#[quickcheck]
1508	fn monad_associativity(
1509		first: String,
1510		second: i32,
1511	) -> bool {
1512		let m = (first, second);
1513		let f = |x: i32| ("f".to_string(), x.wrapping_mul(2));
1514		let g = |x: i32| ("g".to_string(), x.wrapping_add(1));
1515		bind::<Tuple2FirstAppliedBrand<String>, _, _>(
1516			bind::<Tuple2FirstAppliedBrand<String>, _, _>(m.clone(), f),
1517			g,
1518		) == bind::<Tuple2FirstAppliedBrand<String>, _, _>(m, |x| {
1519			bind::<Tuple2FirstAppliedBrand<String>, _, _>(f(x), g)
1520		})
1521	}
1522
1523	// MonadRec tests (Tuple2FirstAppliedBrand)
1524
1525	/// Tests the MonadRec identity law for Tuple2FirstAppliedBrand:
1526	/// `tail_rec_m(|a| pure(Done(a)), x) == pure(x)`.
1527	#[quickcheck]
1528	fn monad_rec_first_identity(x: i32) -> bool {
1529		tail_rec_m::<Tuple2FirstAppliedBrand<String>, _, _>(
1530			|a| (String::new(), ControlFlow::Break(a)),
1531			x,
1532		) == pure::<Tuple2FirstAppliedBrand<String>, _>(x)
1533	}
1534
1535	/// Tests a recursive computation that accumulates the first element.
1536	#[test]
1537	fn monad_rec_first_accumulation() {
1538		let result = tail_rec_m::<Tuple2FirstAppliedBrand<String>, _, _>(
1539			|n: i32| {
1540				if n < 3 {
1541					(format!("{n},"), ControlFlow::Continue(n + 1))
1542				} else {
1543					(format!("{n}"), ControlFlow::Break(n))
1544				}
1545			},
1546			0,
1547		);
1548		assert_eq!(result, ("0,1,2,3".to_string(), 3));
1549	}
1550
1551	/// Tests stack safety for Tuple2FirstAppliedBrand: `tail_rec_m` handles large iteration counts.
1552	#[test]
1553	fn monad_rec_first_stack_safety() {
1554		let iterations: i64 = 200_000;
1555		let result = tail_rec_m::<Tuple2FirstAppliedBrand<String>, _, _>(
1556			|acc| {
1557				if acc < iterations {
1558					(String::new(), ControlFlow::Continue(acc + 1))
1559				} else {
1560					(String::new(), ControlFlow::Break(acc))
1561				}
1562			},
1563			0i64,
1564		);
1565		assert_eq!(result, (String::new(), iterations));
1566	}
1567
1568	// MonadRec tests (Tuple2SecondAppliedBrand)
1569
1570	/// Tests the MonadRec identity law for Tuple2SecondAppliedBrand:
1571	/// `tail_rec_m(|a| pure(Done(a)), x) == pure(x)`.
1572	#[quickcheck]
1573	fn monad_rec_second_identity(x: i32) -> bool {
1574		tail_rec_m::<Tuple2SecondAppliedBrand<String>, _, _>(
1575			|a| (ControlFlow::Break(a), String::new()),
1576			x,
1577		) == pure::<Tuple2SecondAppliedBrand<String>, _>(x)
1578	}
1579
1580	/// Tests a recursive computation that accumulates the second element.
1581	#[test]
1582	fn monad_rec_second_accumulation() {
1583		let result = tail_rec_m::<Tuple2SecondAppliedBrand<String>, _, _>(
1584			|n: i32| {
1585				if n < 3 {
1586					(ControlFlow::Continue(n + 1), format!("{n},"))
1587				} else {
1588					(ControlFlow::Break(n), format!("{n}"))
1589				}
1590			},
1591			0,
1592		);
1593		assert_eq!(result, (3, "0,1,2,3".to_string()));
1594	}
1595
1596	/// Tests stack safety for Tuple2SecondAppliedBrand: `tail_rec_m` handles large iteration counts.
1597	#[test]
1598	fn monad_rec_second_stack_safety() {
1599		let iterations: i64 = 200_000;
1600		let result = tail_rec_m::<Tuple2SecondAppliedBrand<String>, _, _>(
1601			|acc| {
1602				if acc < iterations {
1603					(ControlFlow::Continue(acc + 1), String::new())
1604				} else {
1605					(ControlFlow::Break(acc), String::new())
1606				}
1607			},
1608			0i64,
1609		);
1610		assert_eq!(result, (iterations, String::new()));
1611	}
1612}