Skip to main content

fp_library/types/
pair.rs

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