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!(<Self as Kind!( type Of<'a, T: 'a>: 'a; )>::Of<'a, A>),
67	) -> Apply!(<Self as Kind!( type Of<'a, T: 'a>: 'a; )>::Of<'a, B>)
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!(<Self as Kind!( type Of<'a, T: 'a>: 'a; )>::Of<'a, A>),
116		fb: Apply!(<Self as Kind!( type Of<'a, T: 'a>: 'a; )>::Of<'a, B>),
117	) -> Apply!(<Self as Kind!( type Of<'a, T: 'a>: 'a; )>::Of<'a, C>)
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!(<Self as Kind!( type Of<'a, T: 'a>: 'a; )>::Of<'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!(<Self as Kind!( type Of<'a, T: 'a>: 'a; )>::Of<'a, <FnBrand as ClonableFn>::Of<'a, A, B>>),
207		fa: Apply!(<Self as Kind!( type Of<'a, T: 'a>: 'a; )>::Of<'a, A>),
208	) -> Apply!(<Self as Kind!( type Of<'a, T: 'a>: 'a; )>::Of<'a, B>) {
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!(<Self as Kind!( type Of<'a, T: 'a>: 'a; )>::Of<'a, A>),
251		f: F,
252	) -> Apply!(<Self as Kind!( type Of<'a, T: 'a>: 'a; )>::Of<'a, B>)
253	where
254		F: Fn(A) -> Apply!(<Self as Kind!( type Of<'a, T: 'a>: 'a; )>::Of<'a, B>) + '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!(<Self as Kind!( type Of<'a, T: 'a>: 'a; )>::Of<'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!(<Self as Kind!( type Of<'a, T: 'a>: 'a; )>::Of<'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!(<Self as Kind!( type Of<'a, T: 'a>: 'a; )>::Of<'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!(<Self as Kind!( type Of<'a, T: 'a>: 'a; )>::Of<'a, A>),
438	) -> 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>)>)
439	where
440		Func: Fn(A) -> Apply!(<F as Kind!( type Of<'a, T: 'a>: 'a; )>::Of<'a, B>) + 'a,
441		Apply!(<Self as Kind!( type Of<'a, T: 'a>: 'a; )>::Of<'a, B>): Clone,
442	{
443		F::map(|b| Identity(b), func(ta.0))
444	}
445	/// Sequences an identity of applicative.
446	///
447	/// This method evaluates the computation inside the identity and wraps the result in the applicative context.
448	///
449	/// ### Type Signature
450	///
451	/// `forall a f. (Traversable Identity, Applicative f) => (Identity (f a)) -> f (Identity a)`
452	///
453	/// ### Parameters
454	///
455	/// * `ta`: The identity containing the applicative value.
456	///
457	/// # Returns
458	///
459	/// The identity wrapped in the applicative context.
460	///
461	/// ### Examples
462	///
463	/// ```
464	/// use fp_library::classes::traversable::Traversable;
465	/// use fp_library::brands::{IdentityBrand, OptionBrand};
466	/// use fp_library::types::Identity;
467	///
468	/// let x = Identity(Some(5));
469	/// let y = IdentityBrand::sequence::<OptionBrand, _>(x);
470	/// assert_eq!(y, Some(Identity(5)));
471	///
472	/// // Using the free function
473	/// use fp_library::classes::traversable::sequence;
474	/// assert_eq!(
475	///     sequence::<IdentityBrand, OptionBrand, _>(Identity(Some(5))),
476	///     Some(Identity(5))
477	/// );
478	/// ```
479	fn sequence<'a, F: Applicative, A: 'a + Clone>(
480		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>)>)
481	) -> 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>)>)
482	where
483		Apply!(<F as Kind!( type Of<'a, T: 'a>: 'a; )>::Of<'a, A>): Clone,
484		Apply!(<Self as Kind!( type Of<'a, T: 'a>: 'a; )>::Of<'a, A>): Clone,
485	{
486		F::map(|a| Identity(a), ta.0)
487	}
488}
489
490impl<FnBrand: SendClonableFn> ParFoldable<FnBrand> for IdentityBrand {
491	/// Maps the value to a monoid and returns it in parallel.
492	///
493	/// 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.
494	///
495	/// ### Type Signature
496	///
497	/// `forall a m. (ParFoldable Identity, Monoid m, Send m, Sync m) => (f a m, Identity a) -> m`
498	///
499	/// ### Parameters
500	///
501	/// * `func`: The mapping function.
502	/// * `fa`: The identity to fold.
503	///
504	/// ### Returns
505	///
506	/// The combined monoid value.
507	///
508	/// ### Examples
509	///
510	/// ```
511	/// use fp_library::classes::par_foldable::ParFoldable;
512	/// use fp_library::brands::{IdentityBrand, ArcFnBrand};
513	/// use fp_library::types::Identity;
514	/// use fp_library::classes::send_clonable_fn::SendClonableFn;
515	/// use fp_library::classes::send_clonable_fn::new_send;
516	///
517	/// let x = Identity(1);
518	/// let f = new_send::<ArcFnBrand, _, _>(|x: i32| x.to_string());
519	/// let y = <IdentityBrand as ParFoldable<ArcFnBrand>>::par_fold_map(f, x);
520	/// assert_eq!(y, "1".to_string());
521	///
522	/// // Using the free function
523	/// use fp_library::classes::par_foldable::par_fold_map;
524	/// let x = Identity(1);
525	/// let f = new_send::<ArcFnBrand, _, _>(|x: i32| x.to_string());
526	/// assert_eq!(par_fold_map::<ArcFnBrand, IdentityBrand, _, _>(f, x), "1".to_string());
527	/// ```
528	fn par_fold_map<'a, A, M>(
529		func: <FnBrand as SendClonableFn>::SendOf<'a, A, M>,
530		fa: Apply!(<Self as Kind!( type Of<'a, T: 'a>: 'a; )>::Of<'a, A>),
531	) -> M
532	where
533		A: 'a + Clone + Send + Sync,
534		M: Monoid + Send + Sync + 'a,
535	{
536		func(fa.0)
537	}
538
539	/// Folds the identity from the right in parallel.
540	///
541	/// This method performs a right-associative fold of the identity. Since `Identity` contains only one element, no actual parallelism occurs.
542	///
543	/// ### Type Signature
544	///
545	/// `forall a b. ParFoldable Identity => (f (a, b) b, b, Identity a) -> b`
546	/// ### Parameters
547	///
548	/// * `func`: The thread-safe function to apply to each element and the accumulator.
549	/// * `initial`: The initial value of the accumulator.
550	/// * `fa`: The identity to fold.
551	///
552	/// ### Returns
553	///
554	/// The final accumulator value.
555	///
556	/// ### Examples
557	///
558	/// ```
559	/// use fp_library::classes::par_foldable::ParFoldable;
560	/// use fp_library::brands::{IdentityBrand, ArcFnBrand};
561	/// use fp_library::types::Identity;
562	/// use fp_library::classes::send_clonable_fn::SendClonableFn;
563	/// use fp_library::classes::send_clonable_fn::new_send;
564	///
565	/// let x = Identity(1);
566	/// let f = new_send::<ArcFnBrand, _, _>(|(a, b): (i32, i32)| a + b);
567	/// let y = <IdentityBrand as ParFoldable<ArcFnBrand>>::par_fold_right(f, 10, x);
568	/// assert_eq!(y, 11);
569	///
570	/// // Using the free function
571	/// use fp_library::classes::par_foldable::par_fold_right;
572	/// let x = Identity(1);
573	/// let f = new_send::<ArcFnBrand, _, _>(|(a, b): (i32, i32)| a + b);
574	/// assert_eq!(par_fold_right::<ArcFnBrand, IdentityBrand, _, _>(f, 10, x), 11);
575	/// ```
576	fn par_fold_right<'a, A, B>(
577		func: <FnBrand as SendClonableFn>::SendOf<'a, (A, B), B>,
578		initial: B,
579		fa: Apply!(<Self as Kind!( type Of<'a, T: 'a>: 'a; )>::Of<'a, A>),
580	) -> B
581	where
582		A: 'a + Clone + Send + Sync,
583		B: Send + Sync + 'a,
584	{
585		func((fa.0, initial))
586	}
587}
588
589#[cfg(test)]
590mod tests {
591	use super::*;
592	use crate::{
593		brands::{OptionBrand, RcFnBrand},
594		classes::{functor::map, pointed::pure, semiapplicative::apply, semimonad::bind},
595		functions::{compose, identity},
596	};
597	use quickcheck_macros::quickcheck;
598
599	// Functor Laws
600
601	/// Tests the identity law for Functor.
602	#[quickcheck]
603	fn functor_identity(x: i32) -> bool {
604		let x = Identity(x);
605		map::<IdentityBrand, _, _, _>(identity, x) == x
606	}
607
608	/// Tests the composition law for Functor.
609	#[quickcheck]
610	fn functor_composition(x: i32) -> bool {
611		let x = Identity(x);
612		let f = |x: i32| x.wrapping_add(1);
613		let g = |x: i32| x.wrapping_mul(2);
614		map::<IdentityBrand, _, _, _>(compose(f, g), x)
615			== map::<IdentityBrand, _, _, _>(f, map::<IdentityBrand, _, _, _>(g, x))
616	}
617
618	// Applicative Laws
619
620	/// Tests the identity law for Applicative.
621	#[quickcheck]
622	fn applicative_identity(v: i32) -> bool {
623		let v = Identity(v);
624		apply::<RcFnBrand, IdentityBrand, _, _>(
625			pure::<IdentityBrand, _>(<RcFnBrand as ClonableFn>::new(identity)),
626			v,
627		) == v
628	}
629
630	/// Tests the homomorphism law for Applicative.
631	#[quickcheck]
632	fn applicative_homomorphism(x: i32) -> bool {
633		let f = |x: i32| x.wrapping_mul(2);
634		apply::<RcFnBrand, IdentityBrand, _, _>(
635			pure::<IdentityBrand, _>(<RcFnBrand as ClonableFn>::new(f)),
636			pure::<IdentityBrand, _>(x),
637		) == pure::<IdentityBrand, _>(f(x))
638	}
639
640	/// Tests the composition law for Applicative.
641	#[quickcheck]
642	fn applicative_composition(
643		w: i32,
644		u_val: i32,
645		v_val: i32,
646	) -> bool {
647		let w = Identity(w);
648		let v_fn = move |x: i32| x.wrapping_mul(v_val);
649		let u_fn = move |x: i32| x.wrapping_add(u_val);
650
651		let v = pure::<IdentityBrand, _>(<RcFnBrand as ClonableFn>::new(v_fn));
652		let u = pure::<IdentityBrand, _>(<RcFnBrand as ClonableFn>::new(u_fn));
653
654		// RHS: u <*> (v <*> w)
655		let vw = apply::<RcFnBrand, IdentityBrand, _, _>(v.clone(), w.clone());
656		let rhs = apply::<RcFnBrand, IdentityBrand, _, _>(u.clone(), vw);
657
658		// LHS: pure(compose) <*> u <*> v <*> w
659		// equivalent to (u . v) <*> w
660		let composed = move |x| u_fn(v_fn(x));
661		let uv = pure::<IdentityBrand, _>(<RcFnBrand as ClonableFn>::new(composed));
662
663		let lhs = apply::<RcFnBrand, IdentityBrand, _, _>(uv, w);
664
665		lhs == rhs
666	}
667
668	/// Tests the interchange law for Applicative.
669	#[quickcheck]
670	fn applicative_interchange(y: i32) -> bool {
671		// u <*> pure y = pure ($ y) <*> u
672		let f = |x: i32| x.wrapping_mul(2);
673		let u = pure::<IdentityBrand, _>(<RcFnBrand as ClonableFn>::new(f));
674
675		let lhs = apply::<RcFnBrand, IdentityBrand, _, _>(u.clone(), pure::<IdentityBrand, _>(y));
676
677		let rhs_fn = <RcFnBrand as ClonableFn>::new(move |f: std::rc::Rc<dyn Fn(i32) -> i32>| f(y));
678		let rhs = apply::<RcFnBrand, IdentityBrand, _, _>(pure::<IdentityBrand, _>(rhs_fn), u);
679
680		lhs == rhs
681	}
682
683	// Monad Laws
684
685	/// Tests the left identity law for Monad.
686	#[quickcheck]
687	fn monad_left_identity(a: i32) -> bool {
688		let f = |x: i32| Identity(x.wrapping_mul(2));
689		bind::<IdentityBrand, _, _, _>(pure::<IdentityBrand, _>(a), f) == f(a)
690	}
691
692	/// Tests the right identity law for Monad.
693	#[quickcheck]
694	fn monad_right_identity(m: i32) -> bool {
695		let m = Identity(m);
696		bind::<IdentityBrand, _, _, _>(m, pure::<IdentityBrand, _>) == m
697	}
698
699	/// Tests the associativity law for Monad.
700	#[quickcheck]
701	fn monad_associativity(m: i32) -> bool {
702		let m = Identity(m);
703		let f = |x: i32| Identity(x.wrapping_mul(2));
704		let g = |x: i32| Identity(x.wrapping_add(1));
705		bind::<IdentityBrand, _, _, _>(bind::<IdentityBrand, _, _, _>(m, f), g)
706			== bind::<IdentityBrand, _, _, _>(m, |x| bind::<IdentityBrand, _, _, _>(f(x), g))
707	}
708
709	// Edge Cases
710
711	/// Tests the `map` function.
712	#[test]
713	fn map_test() {
714		assert_eq!(map::<IdentityBrand, _, _, _>(|x: i32| x + 1, Identity(1)), Identity(2));
715	}
716
717	/// Tests the `bind` function.
718	#[test]
719	fn bind_test() {
720		assert_eq!(bind::<IdentityBrand, _, _, _>(Identity(1), |x| Identity(x + 1)), Identity(2));
721	}
722
723	/// Tests the `fold_right` function.
724	#[test]
725	fn fold_right_test() {
726		assert_eq!(
727			crate::classes::foldable::fold_right::<RcFnBrand, IdentityBrand, _, _, _>(
728				|x: i32, acc| x + acc,
729				0,
730				Identity(1)
731			),
732			1
733		);
734	}
735
736	/// Tests the `fold_left` function.
737	#[test]
738	fn fold_left_test() {
739		assert_eq!(
740			crate::classes::foldable::fold_left::<RcFnBrand, IdentityBrand, _, _, _>(
741				|acc, x: i32| acc + x,
742				0,
743				Identity(1)
744			),
745			1
746		);
747	}
748
749	/// Tests the `traverse` function.
750	#[test]
751	fn traverse_test() {
752		assert_eq!(
753			crate::classes::traversable::traverse::<IdentityBrand, OptionBrand, _, _, _>(
754				|x: i32| Some(x + 1),
755				Identity(1)
756			),
757			Some(Identity(2))
758		);
759	}
760
761	// ParFoldable Tests
762
763	/// Tests `par_fold_map`.
764	#[test]
765	fn par_fold_map_test() {
766		use crate::brands::ArcFnBrand;
767		use crate::classes::par_foldable::par_fold_map;
768		use crate::classes::send_clonable_fn::new_send;
769
770		let x = Identity(1);
771		let f = new_send::<ArcFnBrand, _, _>(|x: i32| x.to_string());
772		assert_eq!(par_fold_map::<ArcFnBrand, IdentityBrand, _, _>(f, x), "1".to_string());
773	}
774
775	/// Tests `par_fold_right`.
776	#[test]
777	fn par_fold_right_test() {
778		use crate::brands::ArcFnBrand;
779		use crate::classes::par_foldable::par_fold_right;
780		use crate::classes::send_clonable_fn::new_send;
781
782		let x = Identity(1);
783		let f = new_send::<ArcFnBrand, _, _>(|(a, b): (i32, i32)| a + b);
784		assert_eq!(par_fold_right::<ArcFnBrand, IdentityBrand, _, _>(f, 10, x), 11);
785	}
786}