fp_library/types/
identity.rs

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