Skip to main content

fp_library/types/
identity.rs

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