fp_library/types/
pair.rs

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