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