1#[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 Extend,
17 Extract,
18 Foldable,
19 Functor,
20 Lift,
21 MonadRec,
22 Monoid,
23 Pointed,
24 Semiapplicative,
25 Semimonad,
26 Traversable,
27 },
28 impl_kind,
29 kinds::*,
30 },
31 core::ops::ControlFlow,
32 fp_macros::*,
33 };
34
35 #[document_type_parameters("The type of the wrapped value.")]
49 #[cfg_attr(feature = "serde", derive(serde::Serialize, serde::Deserialize))]
51 #[derive(Clone, Copy, Debug, Default, Eq, Hash, Ord, PartialEq, PartialOrd)]
52 pub struct Identity<A>(
53 pub A,
55 );
56
57 impl_kind! {
58 for IdentityBrand {
59 type Of<'a, A: 'a>: 'a = Identity<A>;
60 }
61 }
62
63 #[document_type_parameters("The type of the wrapped value.")]
64 #[document_parameters("The identity instance.")]
65 impl<A> Identity<A> {
66 #[document_signature]
71 #[document_type_parameters("The type of the result of applying the function.")]
73 #[document_parameters("The function to apply.")]
75 #[document_returns("A new identity containing the result of applying the function.")]
77 #[document_examples]
79 pub fn map<B>(
88 self,
89 f: impl FnOnce(A) -> B,
90 ) -> Identity<B> {
91 Identity(f(self.0))
92 }
93
94 #[document_signature]
98 #[document_type_parameters(
100 "The type of the other identity's value.",
101 "The return type of the function."
102 )]
103 #[document_parameters("The other identity.", "The binary function to apply.")]
105 #[document_returns("A new identity containing the result of applying the function.")]
107 #[document_examples]
109 pub fn lift2<B, C>(
119 self,
120 other: Identity<B>,
121 f: impl FnOnce(A, B) -> C,
122 ) -> Identity<C> {
123 Identity(f(self.0, other.0))
124 }
125
126 #[document_signature]
130 #[document_type_parameters("The return type of the wrapped function.")]
132 #[document_parameters("The identity containing the function.")]
134 #[document_returns("A new identity containing the result.")]
136 #[document_examples]
138 pub fn apply<B>(
148 self,
149 ff: Identity<impl FnOnce(A) -> B>,
150 ) -> Identity<B> {
151 Identity(ff.0(self.0))
152 }
153
154 #[document_signature]
159 #[document_type_parameters("The type of the result of the chained computation.")]
161 #[document_parameters("The function to apply to the value inside the identity.")]
163 #[document_returns("The result of applying `f` to the value.")]
165 #[document_examples]
167 pub fn bind<B>(
176 self,
177 f: impl FnOnce(A) -> Identity<B>,
178 ) -> Identity<B> {
179 f(self.0)
180 }
181
182 #[document_signature]
186 #[document_type_parameters("The type of the accumulator.")]
188 #[document_parameters(
190 "The function to apply to the element and the accumulator.",
191 "The initial value of the accumulator."
192 )]
193 #[document_returns("The final accumulator value.")]
195 #[document_examples]
197 pub fn fold_right<B>(
206 self,
207 f: impl FnOnce(A, B) -> B,
208 initial: B,
209 ) -> B {
210 f(self.0, initial)
211 }
212
213 #[document_signature]
217 #[document_type_parameters("The type of the accumulator.")]
219 #[document_parameters(
221 "The function to apply to the accumulator and the element.",
222 "The initial value of the accumulator."
223 )]
224 #[document_returns("The final accumulator value.")]
226 #[document_examples]
228 pub fn fold_left<B>(
237 self,
238 f: impl FnOnce(B, A) -> B,
239 initial: B,
240 ) -> B {
241 f(initial, self.0)
242 }
243
244 #[document_signature]
248 #[document_type_parameters("The monoid type.")]
250 #[document_parameters("The mapping function.")]
252 #[document_returns("The monoid value.")]
254 #[document_examples]
256 pub fn fold_map<M>(
265 self,
266 f: impl FnOnce(A) -> M,
267 ) -> M {
268 f(self.0)
269 }
270 }
271
272 #[document_type_parameters("The lifetime of the values.", "The type of the wrapped value.")]
273 #[document_parameters("The identity instance.")]
274 impl<'a, A: 'a> Identity<A> {
275 #[document_signature]
279 #[document_type_parameters(
281 "The type of the elements in the resulting identity.",
282 "The applicative context."
283 )]
284 #[document_parameters(
286 "The function to apply, returning a value in an applicative context."
287 )]
288 #[document_returns("The identity wrapped in the applicative context.")]
290 #[document_examples]
292 pub fn traverse<B: 'a + Clone, F: Applicative>(
304 self,
305 f: impl Fn(A) -> Apply!(<F as Kind!( type Of<'a, T: 'a>: 'a; )>::Of<'a, B>) + 'a,
306 ) -> Apply!(<F as Kind!( type Of<'a, T: 'a>: 'a; )>::Of<'a, Identity<B>>)
307 where
308 Identity<B>: Clone, {
309 F::map(|b| Identity(b), f(self.0))
310 }
311
312 #[document_signature]
316 #[document_type_parameters(
318 "The inner type wrapped in the applicative context.",
319 "The applicative context."
320 )]
321 #[document_returns("The identity wrapped in the applicative context.")]
323 #[document_examples]
325 pub fn sequence<InnerA: 'a + Clone, F: Applicative>(
337 self
338 ) -> Apply!(<F as Kind!( type Of<'a, T: 'a>: 'a; )>::Of<'a, Identity<InnerA>>)
339 where
340 A: Into<Apply!(<F as Kind!( type Of<'a, T: 'a>: 'a; )>::Of<'a, InnerA>)>,
341 Identity<InnerA>: Clone, {
342 F::map(|a| Identity(a), self.0.into())
343 }
344 }
345
346 impl Functor for IdentityBrand {
347 #[document_signature]
351 #[document_type_parameters(
353 "The lifetime of the value.",
354 "The type of the value inside the identity.",
355 "The type of the result of applying the function."
356 )]
357 #[document_parameters("The function to apply.", "The identity to map over.")]
359 #[document_returns("A new identity containing the result of applying the function.")]
361 #[document_examples]
363 fn map<'a, A: 'a, B: 'a>(
376 func: impl Fn(A) -> B + 'a,
377 fa: Apply!(<Self as Kind!( type Of<'a, T: 'a>: 'a; )>::Of<'a, A>),
378 ) -> Apply!(<Self as Kind!( type Of<'a, T: 'a>: 'a; )>::Of<'a, B>) {
379 fa.map(func)
380 }
381 }
382
383 impl Lift for IdentityBrand {
384 #[document_signature]
388 #[document_type_parameters(
390 "The lifetime of the values.",
391 "The type of the first identity's value.",
392 "The type of the second identity's value.",
393 "The return type of the function."
394 )]
395 #[document_parameters(
397 "The binary function to apply.",
398 "The first identity.",
399 "The second identity."
400 )]
401 #[document_returns("A new identity containing the result of applying the function.")]
403 #[document_examples]
404 fn lift2<'a, A, B, C>(
418 func: impl Fn(A, B) -> C + 'a,
419 fa: Apply!(<Self as Kind!( type Of<'a, T: 'a>: 'a; )>::Of<'a, A>),
420 fb: Apply!(<Self as Kind!( type Of<'a, T: 'a>: 'a; )>::Of<'a, B>),
421 ) -> Apply!(<Self as Kind!( type Of<'a, T: 'a>: 'a; )>::Of<'a, C>)
422 where
423 A: 'a,
424 B: 'a,
425 C: 'a, {
426 fa.lift2(fb, func)
427 }
428 }
429
430 impl Pointed for IdentityBrand {
431 #[document_signature]
435 #[document_type_parameters("The lifetime of the value.", "The type of the value to wrap.")]
437 #[document_parameters("The value to wrap.")]
439 #[document_returns("An identity containing the value.")]
441 #[document_examples]
443 fn pure<'a, A: 'a>(a: A) -> Apply!(<Self as Kind!( type Of<'a, T: 'a>: 'a; )>::Of<'a, A>) {
455 Identity(a) }
457 }
458
459 impl ApplyFirst for IdentityBrand {}
460 impl ApplySecond for IdentityBrand {}
461
462 impl Semiapplicative for IdentityBrand {
463 #[document_signature]
467 #[document_type_parameters(
469 "The lifetime of the values.",
470 "The brand of the cloneable function wrapper.",
471 "The type of the input value.",
472 "The type of the output value."
473 )]
474 #[document_parameters(
476 "The identity containing the function.",
477 "The identity containing the value."
478 )]
479 #[document_returns("A new identity containing the result of applying the function.")]
481 #[document_examples]
482 fn apply<'a, FnBrand: 'a + CloneableFn, A: 'a + Clone, B: 'a>(
496 ff: Apply!(<Self as Kind!( type Of<'a, T: 'a>: 'a; )>::Of<'a, <FnBrand as CloneableFn>::Of<'a, A, B>>),
497 fa: Apply!(<Self as Kind!( type Of<'a, T: 'a>: 'a; )>::Of<'a, A>),
498 ) -> Apply!(<Self as Kind!( type Of<'a, T: 'a>: 'a; )>::Of<'a, B>) {
499 fa.apply(ff.map(|f| move |a| f(a)))
500 }
501 }
502
503 impl Semimonad for IdentityBrand {
504 #[document_signature]
508 #[document_type_parameters(
510 "The lifetime of the values.",
511 "The type of the result of the first computation.",
512 "The type of the result of the second computation."
513 )]
514 #[document_parameters(
516 "The first identity.",
517 "The function to apply to the value inside the identity."
518 )]
519 #[document_returns("The result of applying `f` to the value.")]
521 #[document_examples]
522 fn bind<'a, A: 'a, B: 'a>(
535 ma: Apply!(<Self as Kind!( type Of<'a, T: 'a>: 'a; )>::Of<'a, A>),
536 func: impl Fn(A) -> Apply!(<Self as Kind!( type Of<'a, T: 'a>: 'a; )>::Of<'a, B>) + 'a,
537 ) -> Apply!(<Self as Kind!( type Of<'a, T: 'a>: 'a; )>::Of<'a, B>) {
538 ma.bind(func)
539 }
540 }
541
542 impl Foldable for IdentityBrand {
543 #[document_signature]
547 #[document_type_parameters(
549 "The lifetime of the values.",
550 "The brand of the cloneable function to use.",
551 "The type of the elements in the structure.",
552 "The type of the accumulator."
553 )]
554 #[document_parameters(
556 "The function to apply to each element and the accumulator.",
557 "The initial value of the accumulator.",
558 "The identity to fold."
559 )]
560 #[document_returns("The final accumulator value.")]
562 #[document_examples]
563 fn fold_right<'a, FnBrand, A: 'a, B: 'a>(
576 func: impl Fn(A, B) -> B + 'a,
577 initial: B,
578 fa: Apply!(<Self as Kind!( type Of<'a, T: 'a>: 'a; )>::Of<'a, A>),
579 ) -> B
580 where
581 FnBrand: CloneableFn + 'a, {
582 fa.fold_right(func, initial)
583 }
584
585 #[document_signature]
589 #[document_type_parameters(
591 "The lifetime of the values.",
592 "The brand of the cloneable function to use.",
593 "The type of the elements in the structure.",
594 "The type of the accumulator."
595 )]
596 #[document_parameters(
598 "The function to apply to the accumulator and each element.",
599 "The initial value of the accumulator.",
600 "The structure to fold."
601 )]
602 #[document_returns("The final accumulator value.")]
604 #[document_examples]
605 fn fold_left<'a, FnBrand, A: 'a, B: 'a>(
618 func: impl Fn(B, A) -> B + 'a,
619 initial: B,
620 fa: Apply!(<Self as Kind!( type Of<'a, T: 'a>: 'a; )>::Of<'a, A>),
621 ) -> B
622 where
623 FnBrand: CloneableFn + 'a, {
624 fa.fold_left(func, initial)
625 }
626
627 #[document_signature]
631 #[document_type_parameters(
633 "The lifetime of the values.",
634 "The brand of the cloneable function to use.",
635 "The type of the elements in the structure.",
636 "The type of the monoid."
637 )]
638 #[document_parameters("The mapping function.", "The identity to fold.")]
640 #[document_returns("The monoid value.")]
642 #[document_examples]
644 fn fold_map<'a, FnBrand, A: 'a, M>(
657 func: impl Fn(A) -> M + 'a,
658 fa: Apply!(<Self as Kind!( type Of<'a, T: 'a>: 'a; )>::Of<'a, A>),
659 ) -> M
660 where
661 M: Monoid + 'a,
662 FnBrand: CloneableFn + 'a, {
663 fa.fold_map(func)
664 }
665 }
666
667 impl Traversable for IdentityBrand {
668 #[document_signature]
672 #[document_type_parameters(
674 "The lifetime of the values.",
675 "The type of the elements in the traversable structure.",
676 "The type of the elements in the resulting traversable structure.",
677 "The applicative context."
678 )]
679 #[document_parameters(
681 "The function to apply to each element, returning a value in an applicative context.",
682 "The identity to traverse."
683 )]
684 #[document_returns("The identity wrapped in the applicative context.")]
686 #[document_examples]
687 fn traverse<'a, A: 'a + Clone, B: 'a + Clone, F: Applicative>(
700 func: impl Fn(A) -> Apply!(<F as Kind!( type Of<'a, T: 'a>: 'a; )>::Of<'a, B>) + 'a,
701 ta: Apply!(<Self as Kind!( type Of<'a, T: 'a>: 'a; )>::Of<'a, A>),
702 ) -> 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>)>)
703 where
704 Apply!(<Self as Kind!( type Of<'a, T: 'a>: 'a; )>::Of<'a, B>): Clone, {
705 ta.traverse::<B, F>(func)
706 }
707
708 #[document_signature]
712 #[document_type_parameters(
714 "The lifetime of the values.",
715 "The type of the elements in the traversable structure.",
716 "The applicative context."
717 )]
718 #[document_parameters("The identity containing the applicative value.")]
720 #[document_returns("The result of the traversal.")]
722 #[document_examples]
727 fn sequence<'a, A: 'a + Clone, F: Applicative>(
740 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>)>)
741 ) -> 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>)>)
742 where
743 Apply!(<F as Kind!( type Of<'a, T: 'a>: 'a; )>::Of<'a, A>): Clone,
744 Apply!(<Self as Kind!( type Of<'a, T: 'a>: 'a; )>::Of<'a, A>): Clone, {
745 ta.traverse::<A, F>(|a| a)
746 }
747 }
748
749 impl MonadRec for IdentityBrand {
750 #[document_signature]
755 #[document_type_parameters(
757 "The lifetime of the computation.",
758 "The type of the initial value and loop state.",
759 "The type of the result."
760 )]
761 #[document_parameters("The step function.", "The initial value.")]
763 #[document_returns("An identity containing the result of the computation.")]
765 #[document_examples]
767 fn tail_rec_m<'a, A: 'a, B: 'a>(
791 func: impl Fn(
792 A,
793 )
794 -> Apply!(<Self as Kind!( type Of<'a, T: 'a>: 'a; )>::Of<'a, ControlFlow<B, A>>)
795 + 'a,
796 initial: A,
797 ) -> Apply!(<Self as Kind!( type Of<'a, T: 'a>: 'a; )>::Of<'a, B>) {
798 let mut current = initial;
799 loop {
800 match func(current).0 {
801 ControlFlow::Continue(next) => current = next,
802 ControlFlow::Break(b) => return Identity(b),
803 }
804 }
805 }
806 }
807
808 impl Extract for IdentityBrand {
809 #[document_signature]
814 #[document_type_parameters(
816 "The lifetime of the value.",
817 "The type of the value inside the identity."
818 )]
819 #[document_parameters("The identity to extract from.")]
821 #[document_returns("The inner value.")]
823 #[document_examples]
825 fn extract<'a, A: 'a>(
837 fa: Apply!(<Self as Kind!( type Of<'a, T: 'a>: 'a; )>::Of<'a, A>)
838 ) -> A {
839 fa.0
840 }
841 }
842
843 impl Extend for IdentityBrand {
844 #[document_signature]
850 #[document_type_parameters(
852 "The lifetime of the values.",
853 "The type of the value inside the identity.",
854 "The result type of the extension function."
855 )]
856 #[document_parameters(
858 "The function that consumes an `Identity` and produces a value.",
859 "The identity to extend over."
860 )]
861 #[document_returns("A new identity containing the result of applying the function.")]
863 #[document_examples]
865 fn extend<'a, A: 'a + Clone, B: 'a>(
878 f: impl Fn(Apply!(<Self as Kind!( type Of<'a, T: 'a>: 'a; )>::Of<'a, A>)) -> B + 'a,
879 wa: Apply!(<Self as Kind!( type Of<'a, T: 'a>: 'a; )>::Of<'a, A>),
880 ) -> Apply!(<Self as Kind!( type Of<'a, T: 'a>: 'a; )>::Of<'a, B>) {
881 Identity(f(wa))
882 }
883 }
884}
885pub use inner::*;
886
887#[cfg(test)]
888mod tests {
889 use {
890 super::inner::Identity,
891 crate::{
892 brands::{
893 IdentityBrand,
894 OptionBrand,
895 RcFnBrand,
896 },
897 classes::{
898 cloneable_fn::CloneableFn,
899 functor::map,
900 pointed::pure,
901 semiapplicative::apply,
902 semimonad::bind,
903 },
904 functions::{
905 compose,
906 identity,
907 },
908 },
909 quickcheck_macros::quickcheck,
910 };
911
912 #[quickcheck]
916 fn functor_identity(x: i32) -> bool {
917 let x = Identity(x);
918 map::<IdentityBrand, _, _>(identity, x) == x
919 }
920
921 #[quickcheck]
923 fn functor_composition(x: i32) -> bool {
924 let x = Identity(x);
925 let f = |x: i32| x.wrapping_add(1);
926 let g = |x: i32| x.wrapping_mul(2);
927 map::<IdentityBrand, _, _>(compose(f, g), x)
928 == map::<IdentityBrand, _, _>(f, map::<IdentityBrand, _, _>(g, x))
929 }
930
931 #[quickcheck]
935 fn applicative_identity(v: i32) -> bool {
936 let v = Identity(v);
937 apply::<RcFnBrand, IdentityBrand, _, _>(
938 pure::<IdentityBrand, _>(<RcFnBrand as CloneableFn>::new(identity)),
939 v,
940 ) == v
941 }
942
943 #[quickcheck]
945 fn applicative_homomorphism(x: i32) -> bool {
946 let f = |x: i32| x.wrapping_mul(2);
947 apply::<RcFnBrand, IdentityBrand, _, _>(
948 pure::<IdentityBrand, _>(<RcFnBrand as CloneableFn>::new(f)),
949 pure::<IdentityBrand, _>(x),
950 ) == pure::<IdentityBrand, _>(f(x))
951 }
952
953 #[quickcheck]
955 fn applicative_composition(
956 w: i32,
957 u_val: i32,
958 v_val: i32,
959 ) -> bool {
960 let w = Identity(w);
961 let v_fn = move |x: i32| x.wrapping_mul(v_val);
962 let u_fn = move |x: i32| x.wrapping_add(u_val);
963
964 let v = pure::<IdentityBrand, _>(<RcFnBrand as CloneableFn>::new(v_fn));
965 let u = pure::<IdentityBrand, _>(<RcFnBrand as CloneableFn>::new(u_fn));
966
967 let vw = apply::<RcFnBrand, IdentityBrand, _, _>(v.clone(), w);
969 let rhs = apply::<RcFnBrand, IdentityBrand, _, _>(u.clone(), vw);
970
971 let composed = move |x| u_fn(v_fn(x));
974 let uv = pure::<IdentityBrand, _>(<RcFnBrand as CloneableFn>::new(composed));
975
976 let lhs = apply::<RcFnBrand, IdentityBrand, _, _>(uv, w);
977
978 lhs == rhs
979 }
980
981 #[quickcheck]
983 fn applicative_interchange(y: i32) -> bool {
984 let f = |x: i32| x.wrapping_mul(2);
986 let u = pure::<IdentityBrand, _>(<RcFnBrand as CloneableFn>::new(f));
987
988 let lhs = apply::<RcFnBrand, IdentityBrand, _, _>(u.clone(), pure::<IdentityBrand, _>(y));
989
990 let rhs_fn =
991 <RcFnBrand as CloneableFn>::new(move |f: std::rc::Rc<dyn Fn(i32) -> i32>| f(y));
992 let rhs = apply::<RcFnBrand, IdentityBrand, _, _>(pure::<IdentityBrand, _>(rhs_fn), u);
993
994 lhs == rhs
995 }
996
997 #[quickcheck]
1001 fn monad_left_identity(a: i32) -> bool {
1002 let f = |x: i32| Identity(x.wrapping_mul(2));
1003 bind::<IdentityBrand, _, _>(pure::<IdentityBrand, _>(a), f) == f(a)
1004 }
1005
1006 #[quickcheck]
1008 fn monad_right_identity(m: i32) -> bool {
1009 let m = Identity(m);
1010 bind::<IdentityBrand, _, _>(m, pure::<IdentityBrand, _>) == m
1011 }
1012
1013 #[quickcheck]
1015 fn monad_associativity(m: i32) -> bool {
1016 let m = Identity(m);
1017 let f = |x: i32| Identity(x.wrapping_mul(2));
1018 let g = |x: i32| Identity(x.wrapping_add(1));
1019 bind::<IdentityBrand, _, _>(bind::<IdentityBrand, _, _>(m, f), g)
1020 == bind::<IdentityBrand, _, _>(m, |x| bind::<IdentityBrand, _, _>(f(x), g))
1021 }
1022
1023 #[test]
1027 fn map_test() {
1028 assert_eq!(map::<IdentityBrand, _, _>(|x: i32| x + 1, Identity(1)), Identity(2));
1029 }
1030
1031 #[test]
1033 fn bind_test() {
1034 assert_eq!(bind::<IdentityBrand, _, _>(Identity(1), |x| Identity(x + 1)), Identity(2));
1035 }
1036
1037 #[test]
1039 fn fold_right_test() {
1040 assert_eq!(
1041 crate::classes::foldable::fold_right::<RcFnBrand, IdentityBrand, _, _>(
1042 |x: i32, acc| x + acc,
1043 0,
1044 Identity(1)
1045 ),
1046 1
1047 );
1048 }
1049
1050 #[test]
1052 fn fold_left_test() {
1053 assert_eq!(
1054 crate::classes::foldable::fold_left::<RcFnBrand, IdentityBrand, _, _>(
1055 |acc, x: i32| acc + x,
1056 0,
1057 Identity(1)
1058 ),
1059 1
1060 );
1061 }
1062
1063 #[test]
1065 fn traverse_test() {
1066 assert_eq!(
1067 crate::classes::traversable::traverse::<IdentityBrand, _, _, OptionBrand>(
1068 |x: i32| Some(x + 1),
1069 Identity(1)
1070 ),
1071 Some(Identity(2))
1072 );
1073 }
1074
1075 #[quickcheck]
1079 fn monad_rec_identity(x: i32) -> bool {
1080 use {
1081 crate::classes::monad_rec::tail_rec_m,
1082 core::ops::ControlFlow,
1083 };
1084 tail_rec_m::<IdentityBrand, _, _>(|a| Identity(ControlFlow::Break(a)), x) == Identity(x)
1085 }
1086
1087 #[test]
1089 fn monad_rec_sum_range() {
1090 use {
1091 crate::classes::monad_rec::tail_rec_m,
1092 core::ops::ControlFlow,
1093 };
1094 let result = tail_rec_m::<IdentityBrand, _, _>(
1095 |(n, acc)| {
1096 if n == 0 {
1097 Identity(ControlFlow::Break(acc))
1098 } else {
1099 Identity(ControlFlow::Continue((n - 1, acc + n)))
1100 }
1101 },
1102 (100i64, 0i64),
1103 );
1104 assert_eq!(result, Identity(5050));
1105 }
1106
1107 #[test]
1109 fn monad_rec_stack_safety() {
1110 use {
1111 crate::classes::monad_rec::tail_rec_m,
1112 core::ops::ControlFlow,
1113 };
1114 let iterations: i64 = 200_000;
1115 let result = tail_rec_m::<IdentityBrand, _, _>(
1116 |acc| {
1117 if acc < iterations {
1118 Identity(ControlFlow::Continue(acc + 1))
1119 } else {
1120 Identity(ControlFlow::Break(acc))
1121 }
1122 },
1123 0i64,
1124 );
1125 assert_eq!(result, Identity(iterations));
1126 }
1127
1128 #[quickcheck]
1132 fn extract_pure(x: i32) -> bool {
1133 use crate::classes::extract::extract;
1134 extract::<IdentityBrand, _>(pure::<IdentityBrand, _>(x)) == x
1135 }
1136
1137 #[quickcheck]
1139 fn comonad_left_identity(x: i32) -> bool {
1140 use crate::classes::{
1141 extend::extend,
1142 extract::extract,
1143 };
1144 let f = |w: Identity<i32>| w.0.wrapping_mul(3);
1145 let wa = Identity(x);
1146 extract::<IdentityBrand, _>(extend::<IdentityBrand, _, _>(f, wa)) == f(wa)
1147 }
1148
1149 #[quickcheck]
1151 fn comonad_right_identity(x: i32) -> bool {
1152 use crate::classes::{
1153 extend::extend,
1154 extract::extract,
1155 };
1156 extend::<IdentityBrand, _, _>(extract::<IdentityBrand, _>, Identity(x)) == Identity(x)
1157 }
1158
1159 #[quickcheck]
1161 fn extend_associativity(x: i32) -> bool {
1162 use crate::classes::extend::extend;
1163 let g = |w: Identity<i32>| w.0.wrapping_mul(2);
1164 let f = |w: Identity<i32>| w.0.wrapping_add(1);
1165 let wa = Identity(x);
1166 let lhs = extend::<IdentityBrand, _, _>(f, extend::<IdentityBrand, _, _>(g, wa));
1167 let rhs = extend::<IdentityBrand, _, _>(
1168 |w: Identity<i32>| f(extend::<IdentityBrand, _, _>(g, w)),
1169 wa,
1170 );
1171 lhs == rhs
1172 }
1173
1174 #[quickcheck]
1176 fn comonad_map_extract(x: i32) -> bool {
1177 use crate::classes::extract::extract;
1178 let f = |a: i32| a.wrapping_mul(5);
1179 let wa = Identity(x);
1180 extract::<IdentityBrand, _>(map::<IdentityBrand, _, _>(f, wa))
1181 == f(extract::<IdentityBrand, _>(wa))
1182 }
1183
1184 #[test]
1186 fn extract_test() {
1187 use crate::classes::extract::extract;
1188 assert_eq!(extract::<IdentityBrand, _>(Identity(42)), 42);
1189 }
1190
1191 #[test]
1193 fn extend_test() {
1194 use crate::classes::extend::extend;
1195 let result = extend::<IdentityBrand, _, _>(|w: Identity<i32>| w.0 * 2, Identity(21));
1196 assert_eq!(result, Identity(42));
1197 }
1198}