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