Skip to main content

fp_library/types/
pair.rs

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