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