Skip to main content

fp_library/types/
tuple_1.rs

1//! Single-value tuple with [`Functor`](crate::classes::Functor), [`Applicative`](crate::classes::Applicative), [`Monad`](crate::classes::Monad), [`Foldable`](crate::classes::Foldable), [`Traversable`](crate::classes::Traversable), and parallel folding instances.
2//!
3//! A trivial wrapper using the native Rust 1-tuple `(A,)`.
4
5#[fp_macros::document_module]
6mod inner {
7	use {
8		crate::{
9			Apply,
10			brands::Tuple1Brand,
11			classes::{
12				Applicative,
13				ApplyFirst,
14				ApplySecond,
15				CloneableFn,
16				Foldable,
17				Functor,
18				Lift,
19				Monoid,
20				ParFoldable,
21				Pointed,
22				Semiapplicative,
23				Semimonad,
24				SendCloneableFn,
25				Traversable,
26			},
27			impl_kind,
28			kinds::*,
29		},
30		fp_macros::*,
31	};
32
33	impl_kind! {
34		for Tuple1Brand {
35			type Of<A> = (A,);
36		}
37	}
38
39	impl_kind! {
40		for Tuple1Brand {
41			type Of<'a, A: 'a>: 'a = (A,);
42		}
43	}
44
45	impl Functor for Tuple1Brand {
46		/// Maps a function over the value in the tuple.
47		///
48		/// This method applies a function to the value inside the 1-tuple, producing a new 1-tuple with the transformed value.
49		#[document_signature]
50		///
51		#[document_type_parameters(
52			"The lifetime of the value.",
53			"The type of the value inside the tuple.",
54			"The type of the result of applying the function."
55		)]
56		///
57		#[document_parameters("The function to apply.", "The tuple to map over.")]
58		///
59		#[document_returns("A new 1-tuple containing the result of applying the function.")]
60		///
61		#[document_examples]
62		///
63		/// ```
64		/// use fp_library::{
65		/// 	brands::*,
66		/// 	functions::*,
67		/// };
68		///
69		/// let x = (5,);
70		/// let y = map::<Tuple1Brand, _, _>(|i| i * 2, x);
71		/// assert_eq!(y, (10,));
72		/// ```
73		fn map<'a, A: 'a, B: 'a>(
74			func: impl Fn(A) -> B + 'a,
75			fa: Apply!(<Self as Kind!( type Of<'a, T: 'a>: 'a; )>::Of<'a, A>),
76		) -> Apply!(<Self as Kind!( type Of<'a, T: 'a>: 'a; )>::Of<'a, B>) {
77			(func(fa.0),)
78		}
79	}
80
81	impl Lift for Tuple1Brand {
82		/// Lifts a binary function into the tuple context.
83		///
84		/// This method lifts a binary function to operate on values within the 1-tuple context.
85		#[document_signature]
86		///
87		#[document_type_parameters(
88			"The lifetime of the values.",
89			"The type of the first tuple's value.",
90			"The type of the second tuple's value.",
91			"The return type of the function."
92		)]
93		///
94		#[document_parameters(
95			"The binary function to apply.",
96			"The first tuple.",
97			"The second tuple."
98		)]
99		///
100		#[document_returns("A new 1-tuple containing the result of applying the function.")]
101		#[document_examples]
102		///
103		/// ```
104		/// use fp_library::{
105		/// 	brands::*,
106		/// 	functions::*,
107		/// };
108		///
109		/// let x = (1,);
110		/// let y = (2,);
111		/// let z = lift2::<Tuple1Brand, _, _, _>(|a, b| a + b, x, y);
112		/// assert_eq!(z, (3,));
113		/// ```
114		fn lift2<'a, A, B, C>(
115			func: impl Fn(A, B) -> C + 'a,
116			fa: Apply!(<Self as Kind!( type Of<'a, T: 'a>: 'a; )>::Of<'a, A>),
117			fb: Apply!(<Self as Kind!( type Of<'a, T: 'a>: 'a; )>::Of<'a, B>),
118		) -> Apply!(<Self as Kind!( type Of<'a, T: 'a>: 'a; )>::Of<'a, C>)
119		where
120			A: 'a,
121			B: 'a,
122			C: 'a, {
123			(func(fa.0, fb.0),)
124		}
125	}
126
127	impl Pointed for Tuple1Brand {
128		/// Wraps a value in a 1-tuple.
129		///
130		/// This method wraps a value in a 1-tuple context.
131		#[document_signature]
132		///
133		#[document_type_parameters("The lifetime of the value.", "The type of the value to wrap.")]
134		///
135		#[document_parameters("The value to wrap.")]
136		///
137		#[document_returns("A 1-tuple containing the value.")]
138		///
139		#[document_examples]
140		///
141		/// ```
142		/// use fp_library::{
143		/// 	brands::*,
144		/// 	functions::*,
145		/// };
146		///
147		/// let x = pure::<Tuple1Brand, _>(5);
148		/// assert_eq!(x, (5,));
149		/// ```
150		fn pure<'a, A: 'a>(a: A) -> Apply!(<Self as Kind!( type Of<'a, T: 'a>: 'a; )>::Of<'a, A>) {
151			(a,)
152		}
153	}
154
155	impl ApplyFirst for Tuple1Brand {}
156	impl ApplySecond for Tuple1Brand {}
157
158	impl Semiapplicative for Tuple1Brand {
159		/// Applies a wrapped function to a wrapped value.
160		///
161		/// This method applies a function wrapped in a 1-tuple to a value wrapped in a 1-tuple.
162		#[document_signature]
163		///
164		#[document_type_parameters(
165			"The lifetime of the values.",
166			"The brand of the cloneable function wrapper.",
167			"The type of the input value.",
168			"The type of the output value."
169		)]
170		///
171		#[document_parameters(
172			"The tuple containing the function.",
173			"The tuple containing the value."
174		)]
175		///
176		#[document_returns("A new 1-tuple containing the result of applying the function.")]
177		#[document_examples]
178		///
179		/// ```
180		/// use fp_library::{
181		/// 	brands::*,
182		/// 	functions::*,
183		/// };
184		///
185		/// let f = (cloneable_fn_new::<RcFnBrand, _, _>(|x: i32| x * 2),);
186		/// let x = (5,);
187		/// let y = apply::<RcFnBrand, Tuple1Brand, _, _>(f, x);
188		/// assert_eq!(y, (10,));
189		/// ```
190		fn apply<'a, FnBrand: 'a + CloneableFn, A: 'a + Clone, B: 'a>(
191			ff: Apply!(<Self as Kind!( type Of<'a, T: 'a>: 'a; )>::Of<'a, <FnBrand as CloneableFn>::Of<'a, A, B>>),
192			fa: Apply!(<Self as Kind!( type Of<'a, T: 'a>: 'a; )>::Of<'a, A>),
193		) -> Apply!(<Self as Kind!( type Of<'a, T: 'a>: 'a; )>::Of<'a, B>) {
194			(ff.0(fa.0),)
195		}
196	}
197
198	impl Semimonad for Tuple1Brand {
199		/// Chains 1-tuple computations.
200		///
201		/// This method chains two 1-tuple computations, where the second computation depends on the result of the first.
202		#[document_signature]
203		///
204		#[document_type_parameters(
205			"The lifetime of the values.",
206			"The type of the result of the first computation.",
207			"The type of the result of the second computation."
208		)]
209		///
210		#[document_parameters(
211			"The first tuple.",
212			"The function to apply to the value inside the tuple."
213		)]
214		///
215		#[document_returns("The result of applying `f` to the value.")]
216		#[document_examples]
217		///
218		/// ```
219		/// use fp_library::{
220		/// 	brands::*,
221		/// 	functions::*,
222		/// };
223		///
224		/// let x = (5,);
225		/// let y = bind::<Tuple1Brand, _, _>(x, |i| (i * 2,));
226		/// assert_eq!(y, (10,));
227		/// ```
228		fn bind<'a, A: 'a, B: 'a>(
229			ma: Apply!(<Self as Kind!( type Of<'a, T: 'a>: 'a; )>::Of<'a, A>),
230			func: impl Fn(A) -> Apply!(<Self as Kind!( type Of<'a, T: 'a>: 'a; )>::Of<'a, B>) + 'a,
231		) -> Apply!(<Self as Kind!( type Of<'a, T: 'a>: 'a; )>::Of<'a, B>) {
232			func(ma.0)
233		}
234	}
235
236	impl Foldable for Tuple1Brand {
237		/// Folds the 1-tuple from the right.
238		///
239		/// This method performs a right-associative fold of the 1-tuple. Since it contains only one element, this is equivalent to applying the function to the element and the initial value.
240		#[document_signature]
241		///
242		#[document_type_parameters(
243			"The lifetime of the values.",
244			"The brand of the cloneable function to use.",
245			"The type of the elements in the structure.",
246			"The type of the accumulator."
247		)]
248		///
249		#[document_parameters(
250			"The function to apply to each element and the accumulator.",
251			"The initial value of the accumulator.",
252			"The tuple to fold."
253		)]
254		///
255		#[document_returns("The final accumulator value.")]
256		#[document_examples]
257		///
258		/// ```
259		/// use fp_library::{
260		/// 	brands::*,
261		/// 	functions::*,
262		/// };
263		///
264		/// let x = (5,);
265		/// let y = fold_right::<RcFnBrand, Tuple1Brand, _, _>(|a, b| a + b, 10, x);
266		/// assert_eq!(y, 15);
267		/// ```
268		fn fold_right<'a, FnBrand, A: 'a + Clone, B: 'a>(
269			func: impl Fn(A, B) -> B + 'a,
270			initial: B,
271			fa: Apply!(<Self as Kind!( type Of<'a, T: 'a>: 'a; )>::Of<'a, A>),
272		) -> B
273		where
274			FnBrand: CloneableFn + 'a, {
275			func(fa.0, initial)
276		}
277
278		/// Folds the 1-tuple from the left.
279		///
280		/// This method performs a left-associative fold of the 1-tuple. Since it contains only one element, this is equivalent to applying the function to the initial value and the element.
281		#[document_signature]
282		///
283		#[document_type_parameters(
284			"The lifetime of the values.",
285			"The brand of the cloneable function to use.",
286			"The type of the elements in the structure.",
287			"The type of the accumulator."
288		)]
289		///
290		#[document_parameters(
291			"The function to apply to the accumulator and each element.",
292			"The initial value of the accumulator.",
293			"The tuple to fold."
294		)]
295		///
296		#[document_returns("The final accumulator value.")]
297		#[document_examples]
298		///
299		/// ```
300		/// use fp_library::{
301		/// 	brands::*,
302		/// 	functions::*,
303		/// };
304		///
305		/// let x = (5,);
306		/// let y = fold_left::<RcFnBrand, Tuple1Brand, _, _>(|b, a| b + a, 10, x);
307		/// assert_eq!(y, 15);
308		/// ```
309		fn fold_left<'a, FnBrand, A: 'a + Clone, B: 'a>(
310			func: impl Fn(B, A) -> B + 'a,
311			initial: B,
312			fa: Apply!(<Self as Kind!( type Of<'a, T: 'a>: 'a; )>::Of<'a, A>),
313		) -> B
314		where
315			FnBrand: CloneableFn + 'a, {
316			func(initial, fa.0)
317		}
318
319		/// Maps the value to a monoid and returns it.
320		///
321		/// This method maps the element of the 1-tuple to a monoid.
322		#[document_signature]
323		///
324		#[document_type_parameters(
325			"The lifetime of the values.",
326			"The brand of the cloneable function to use.",
327			"The type of the elements in the structure.",
328			"The type of the monoid."
329		)]
330		///
331		#[document_parameters(
332			"The thread-safe function to map each element to a monoid.",
333			"The tuple to fold."
334		)]
335		///
336		#[document_returns("The monoid value.")]
337		#[document_examples]
338		///
339		/// ```
340		/// use fp_library::{
341		/// 	brands::*,
342		/// 	functions::*,
343		/// };
344		///
345		/// let x = (5,);
346		/// let y = fold_map::<RcFnBrand, Tuple1Brand, _, _>(|a: i32| a.to_string(), x);
347		/// assert_eq!(y, "5".to_string());
348		/// ```
349		fn fold_map<'a, FnBrand, A: 'a + Clone, M>(
350			func: impl Fn(A) -> M + 'a,
351			fa: Apply!(<Self as Kind!( type Of<'a, T: 'a>: 'a; )>::Of<'a, A>),
352		) -> M
353		where
354			M: Monoid + 'a,
355			FnBrand: CloneableFn + 'a, {
356			func(fa.0)
357		}
358	}
359
360	impl Traversable for Tuple1Brand {
361		/// Traverses the 1-tuple with an applicative function.
362		///
363		/// This method maps the element of the 1-tuple to a computation, evaluates it, and wraps the result in the applicative context.
364		#[document_signature]
365		///
366		#[document_type_parameters(
367			"The lifetime of the values.",
368			"The type of the elements in the traversable structure.",
369			"The type of the elements in the resulting traversable structure.",
370			"The applicative context."
371		)]
372		///
373		#[document_parameters(
374			"The function to apply to each element, returning a value in an applicative context.",
375			"The tuple to traverse."
376		)]
377		///
378		#[document_returns("The 1-tuple wrapped in the applicative context.")]
379		#[document_examples]
380		///
381		/// ```
382		/// use fp_library::{
383		/// 	brands::*,
384		/// 	functions::*,
385		/// };
386		///
387		/// let x = (5,);
388		/// let y = traverse::<Tuple1Brand, _, _, OptionBrand>(|a| Some(a * 2), x);
389		/// assert_eq!(y, Some((10,)));
390		/// ```
391		fn traverse<'a, A: 'a + Clone, B: 'a + Clone, F: Applicative>(
392			func: impl Fn(A) -> Apply!(<F as Kind!( type Of<'a, T: 'a>: 'a; )>::Of<'a, B>) + 'a,
393			ta: Apply!(<Self as Kind!( type Of<'a, T: 'a>: 'a; )>::Of<'a, A>),
394		) -> 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>)>)
395		where
396			Apply!(<Self as Kind!( type Of<'a, T: 'a>: 'a; )>::Of<'a, B>): Clone, {
397			F::map(|b| (b,), func(ta.0))
398		}
399
400		/// Sequences a 1-tuple of applicative.
401		///
402		/// This method evaluates the computation inside the 1-tuple and wraps the result in the applicative context.
403		#[document_signature]
404		///
405		#[document_type_parameters(
406			"The lifetime of the values.",
407			"The type of the elements in the traversable structure.",
408			"The applicative context."
409		)]
410		///
411		#[document_parameters("The tuple containing the applicative value.")]
412		///
413		#[document_returns("The 1-tuple wrapped in the applicative context.")]
414		///
415		#[document_examples]
416		///
417		/// ```
418		/// use fp_library::{
419		/// 	brands::*,
420		/// 	functions::*,
421		/// };
422		///
423		/// let x = (Some(5),);
424		/// let y = sequence::<Tuple1Brand, _, OptionBrand>(x);
425		/// assert_eq!(y, Some((5,)));
426		/// ```
427		fn sequence<'a, A: 'a + Clone, F: Applicative>(
428			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>)>)
429		) -> 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>)>)
430		where
431			Apply!(<F as Kind!( type Of<'a, T: 'a>: 'a; )>::Of<'a, A>): Clone,
432			Apply!(<Self as Kind!( type Of<'a, T: 'a>: 'a; )>::Of<'a, A>): Clone, {
433			F::map(|a| (a,), ta.0)
434		}
435	}
436
437	impl ParFoldable for Tuple1Brand {
438		/// Maps the value to a monoid and returns it in parallel.
439		///
440		/// This method maps the element of the 1-tuple to a monoid. Since it contains only one element, no actual parallelism occurs, but the interface is satisfied.
441		#[document_signature]
442		///
443		#[document_type_parameters(
444			"The lifetime of the values.",
445			"The brand of the cloneable function wrapper.",
446			"The element type.",
447			"The monoid type."
448		)]
449		///
450		#[document_parameters(
451			"The function to map each element to a monoid.",
452			"The tuple to fold."
453		)]
454		///
455		#[document_returns("The combined monoid value.")]
456		#[document_examples]
457		///
458		/// ```
459		/// use fp_library::{
460		/// 	brands::*,
461		/// 	functions::*,
462		/// };
463		///
464		/// let x = (1,);
465		/// let f = send_cloneable_fn_new::<ArcFnBrand, _, _>(|x: i32| x.to_string());
466		/// let y = par_fold_map::<ArcFnBrand, Tuple1Brand, _, _>(f, x);
467		/// assert_eq!(y, "1".to_string());
468		/// ```
469		fn par_fold_map<'a, FnBrand, A, M>(
470			func: <FnBrand as SendCloneableFn>::SendOf<'a, A, M>,
471			fa: Apply!(<Self as Kind!( type Of<'a, T: 'a>: 'a; )>::Of<'a, A>),
472		) -> M
473		where
474			FnBrand: 'a + SendCloneableFn,
475			A: 'a + Clone + Send + Sync,
476			M: Monoid + Send + Sync + 'a, {
477			func(fa.0)
478		}
479
480		/// Folds the 1-tuple from the right in parallel.
481		///
482		/// This method performs a right-associative fold of the 1-tuple. Since it contains only one element, no actual parallelism occurs.
483		#[document_signature]
484		///
485		#[document_type_parameters(
486			"The lifetime of the values.",
487			"The brand of the cloneable function wrapper.",
488			"The element type.",
489			"The accumulator type."
490		)]
491		///
492		#[document_parameters(
493			"The thread-safe function to apply to each element and the accumulator.",
494			"The initial value of the accumulator.",
495			"The tuple to fold."
496		)]
497		///
498		#[document_returns("The final accumulator value.")]
499		#[document_examples]
500		///
501		/// ```
502		/// use fp_library::{
503		/// 	brands::*,
504		/// 	functions::*,
505		/// };
506		///
507		/// let x = (1,);
508		/// let f = send_cloneable_fn_new::<ArcFnBrand, _, _>(|(a, b): (i32, i32)| a + b);
509		/// let y = par_fold_right::<ArcFnBrand, Tuple1Brand, _, _>(f, 10, x);
510		/// assert_eq!(y, 11);
511		/// ```
512		fn par_fold_right<'a, FnBrand, A, B>(
513			func: <FnBrand as SendCloneableFn>::SendOf<'a, (A, B), B>,
514			initial: B,
515			fa: Apply!(<Self as Kind!( type Of<'a, T: 'a>: 'a; )>::Of<'a, A>),
516		) -> B
517		where
518			FnBrand: 'a + SendCloneableFn,
519			A: 'a + Clone + Send + Sync,
520			B: Send + Sync + 'a, {
521			func((fa.0, initial))
522		}
523	}
524}
525
526#[cfg(test)]
527mod tests {
528
529	use {
530		crate::{
531			brands::{
532				OptionBrand,
533				RcFnBrand,
534				Tuple1Brand,
535			},
536			classes::{
537				CloneableFn,
538				functor::map,
539				pointed::pure,
540				semiapplicative::apply,
541				semimonad::bind,
542			},
543			functions::{
544				compose,
545				identity,
546			},
547		},
548		quickcheck_macros::quickcheck,
549	};
550
551	// Functor Laws
552
553	/// Tests the identity law for Functor.
554	#[quickcheck]
555	fn functor_identity(x: i32) -> bool {
556		let x = (x,);
557		map::<Tuple1Brand, _, _>(identity, x) == x
558	}
559
560	/// Tests the composition law for Functor.
561	#[quickcheck]
562	fn functor_composition(x: i32) -> bool {
563		let x = (x,);
564		let f = |x: i32| x.wrapping_add(1);
565		let g = |x: i32| x.wrapping_mul(2);
566		map::<Tuple1Brand, _, _>(compose(f, g), x)
567			== map::<Tuple1Brand, _, _>(f, map::<Tuple1Brand, _, _>(g, x))
568	}
569
570	// Applicative Laws
571
572	/// Tests the identity law for Applicative.
573	#[quickcheck]
574	fn applicative_identity(v: i32) -> bool {
575		let v = (v,);
576		apply::<RcFnBrand, Tuple1Brand, _, _>(
577			pure::<Tuple1Brand, _>(<RcFnBrand as CloneableFn>::new(identity)),
578			v,
579		) == v
580	}
581
582	/// Tests the homomorphism law for Applicative.
583	#[quickcheck]
584	fn applicative_homomorphism(x: i32) -> bool {
585		let f = |x: i32| x.wrapping_mul(2);
586		apply::<RcFnBrand, Tuple1Brand, _, _>(
587			pure::<Tuple1Brand, _>(<RcFnBrand as CloneableFn>::new(f)),
588			pure::<Tuple1Brand, _>(x),
589		) == pure::<Tuple1Brand, _>(f(x))
590	}
591
592	/// Tests the composition law for Applicative.
593	#[quickcheck]
594	fn applicative_composition(
595		w: i32,
596		u_val: i32,
597		v_val: i32,
598	) -> bool {
599		let w = (w,);
600		let v_fn = move |x: i32| x.wrapping_mul(v_val);
601		let u_fn = move |x: i32| x.wrapping_add(u_val);
602
603		let v = pure::<Tuple1Brand, _>(<RcFnBrand as CloneableFn>::new(v_fn));
604		let u = pure::<Tuple1Brand, _>(<RcFnBrand as CloneableFn>::new(u_fn));
605
606		// RHS: u <*> (v <*> w)
607		let vw = apply::<RcFnBrand, Tuple1Brand, _, _>(v.clone(), w);
608		let rhs = apply::<RcFnBrand, Tuple1Brand, _, _>(u.clone(), vw);
609
610		// LHS: pure(compose) <*> u <*> v <*> w
611		let composed = move |x| u_fn(v_fn(x));
612		let uv = pure::<Tuple1Brand, _>(<RcFnBrand as CloneableFn>::new(composed));
613
614		let lhs = apply::<RcFnBrand, Tuple1Brand, _, _>(uv, w);
615
616		lhs == rhs
617	}
618
619	/// Tests the interchange law for Applicative.
620	#[quickcheck]
621	fn applicative_interchange(y: i32) -> bool {
622		// u <*> pure y = pure ($ y) <*> u
623		let f = |x: i32| x.wrapping_mul(2);
624		let u = pure::<Tuple1Brand, _>(<RcFnBrand as CloneableFn>::new(f));
625
626		let lhs = apply::<RcFnBrand, Tuple1Brand, _, _>(u.clone(), pure::<Tuple1Brand, _>(y));
627
628		let rhs_fn =
629			<RcFnBrand as CloneableFn>::new(move |f: std::rc::Rc<dyn Fn(i32) -> i32>| f(y));
630		let rhs = apply::<RcFnBrand, Tuple1Brand, _, _>(pure::<Tuple1Brand, _>(rhs_fn), u);
631
632		lhs == rhs
633	}
634
635	// Monad Laws
636
637	/// Tests the left identity law for Monad.
638	#[quickcheck]
639	fn monad_left_identity(a: i32) -> bool {
640		let f = |x: i32| (x.wrapping_mul(2),);
641		bind::<Tuple1Brand, _, _>(pure::<Tuple1Brand, _>(a), f) == f(a)
642	}
643
644	/// Tests the right identity law for Monad.
645	#[quickcheck]
646	fn monad_right_identity(m: i32) -> bool {
647		let m = (m,);
648		bind::<Tuple1Brand, _, _>(m, pure::<Tuple1Brand, _>) == m
649	}
650
651	/// Tests the associativity law for Monad.
652	#[quickcheck]
653	fn monad_associativity(m: i32) -> bool {
654		let m = (m,);
655		let f = |x: i32| (x.wrapping_mul(2),);
656		let g = |x: i32| (x.wrapping_add(1),);
657		bind::<Tuple1Brand, _, _>(bind::<Tuple1Brand, _, _>(m, f), g)
658			== bind::<Tuple1Brand, _, _>(m, |x| bind::<Tuple1Brand, _, _>(f(x), g))
659	}
660
661	// Edge Cases
662
663	/// Tests the `map` function.
664	#[test]
665	fn map_test() {
666		assert_eq!(map::<Tuple1Brand, _, _>(|x: i32| x + 1, (1,)), (2,));
667	}
668
669	/// Tests the `bind` function.
670	#[test]
671	fn bind_test() {
672		assert_eq!(bind::<Tuple1Brand, _, _>((1,), |x| (x + 1,)), (2,));
673	}
674
675	/// Tests the `fold_right` function.
676	#[test]
677	fn fold_right_test() {
678		assert_eq!(
679			crate::classes::foldable::fold_right::<RcFnBrand, Tuple1Brand, _, _>(
680				|x: i32, acc| x + acc,
681				0,
682				(1,)
683			),
684			1
685		);
686	}
687
688	/// Tests the `fold_left` function.
689	#[test]
690	fn fold_left_test() {
691		assert_eq!(
692			crate::classes::foldable::fold_left::<RcFnBrand, Tuple1Brand, _, _>(
693				|acc, x: i32| acc + x,
694				0,
695				(1,)
696			),
697			1
698		);
699	}
700
701	/// Tests the `traverse` function.
702	#[test]
703	fn traverse_test() {
704		assert_eq!(
705			crate::classes::traversable::traverse::<Tuple1Brand, _, _, OptionBrand>(
706				|x: i32| Some(x + 1),
707				(1,)
708			),
709			Some((2,))
710		);
711	}
712
713	// ParFoldable Tests
714
715	/// Tests `par_fold_map`.
716	#[test]
717	fn par_fold_map_test() {
718		use crate::{
719			brands::*,
720			functions::*,
721		};
722
723		let x = (1,);
724		let f = send_cloneable_fn_new::<ArcFnBrand, _, _>(|x: i32| x.to_string());
725		assert_eq!(par_fold_map::<ArcFnBrand, Tuple1Brand, _, _>(f, x), "1".to_string());
726	}
727
728	/// Tests `par_fold_right`.
729	#[test]
730	fn par_fold_right_test() {
731		use crate::{
732			brands::*,
733			functions::*,
734		};
735
736		let x = (1,);
737		let f = send_cloneable_fn_new::<ArcFnBrand, _, _>(|(a, b): (i32, i32)| a + b);
738		assert_eq!(par_fold_right::<ArcFnBrand, Tuple1Brand, _, _>(f, 10, x), 11);
739	}
740}