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