Skip to main content

fp_library/types/
pair.rs

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