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