Skip to main content

fp_library/types/
identity.rs

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