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