fp_library/types/
pair.rs

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