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