Skip to main content

fp_library/types/
pair.rs

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