Skip to main content

fp_library/types/
identity.rs

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