1use crate::{
6 Apply,
7 brands::IdentityBrand,
8 classes::{
9 Applicative, ApplyFirst, ApplySecond, CloneableFn, Foldable, Functor, Lift, Monoid,
10 ParFoldable, Pointed, Semiapplicative, Semimonad, SendCloneableFn, Traversable,
11 },
12 impl_kind,
13 kinds::*,
14};
15use fp_macros::{doc_params, doc_type_params, hm_signature};
16
17#[derive(Clone, Copy, Debug, Default, Eq, Hash, Ord, PartialEq, PartialOrd)]
39pub struct Identity<A>(pub A);
40
41impl_kind! {
42 for IdentityBrand {
43 type Of<'a, A: 'a>: 'a = Identity<A>;
44 }
45}
46
47impl Functor for IdentityBrand {
48 #[hm_signature(Functor)]
55 #[doc_type_params(
59 "The lifetime of the value.",
60 "The type of the value inside the identity.",
61 "The type of the result of applying the function.",
62 "The type of the function to apply."
63 )]
64 #[doc_params("The function to apply.", "The identity to map over.")]
68 fn map<'a, A: 'a, B: 'a, Func>(
83 func: Func,
84 fa: Apply!(<Self as Kind!( type Of<'a, T: 'a>: 'a; )>::Of<'a, A>),
85 ) -> Apply!(<Self as Kind!( type Of<'a, T: 'a>: 'a; )>::Of<'a, B>)
86 where
87 Func: Fn(A) -> B + 'a,
88 {
89 Identity(func(fa.0))
90 }
91}
92
93impl Lift for IdentityBrand {
94 #[hm_signature(Lift)]
101 #[doc_type_params(
105 "The lifetime of the values.",
106 "The type of the first identity's value.",
107 "The type of the second identity's value.",
108 "The return type of the function.",
109 "The type of the binary function."
110 )]
111 #[doc_params("The binary function to apply.", "The first identity.", "The second identity.")]
115 fn lift2<'a, A, B, C, Func>(
131 func: Func,
132 fa: Apply!(<Self as Kind!( type Of<'a, T: 'a>: 'a; )>::Of<'a, A>),
133 fb: Apply!(<Self as Kind!( type Of<'a, T: 'a>: 'a; )>::Of<'a, B>),
134 ) -> Apply!(<Self as Kind!( type Of<'a, T: 'a>: 'a; )>::Of<'a, C>)
135 where
136 Func: Fn(A, B) -> C + 'a,
137 A: 'a,
138 B: 'a,
139 C: 'a,
140 {
141 Identity(func(fa.0, fb.0))
142 }
143}
144
145impl Pointed for IdentityBrand {
146 #[hm_signature(Pointed)]
153 #[doc_type_params("The lifetime of the value.", "The type of the value to wrap.")]
157 #[doc_params("The value to wrap.")]
161 fn pure<'a, A: 'a>(a: A) -> Apply!(<Self as Kind!( type Of<'a, T: 'a>: 'a; )>::Of<'a, A>) {
175 Identity(a)
176 }
177}
178
179impl ApplyFirst for IdentityBrand {}
180impl ApplySecond for IdentityBrand {}
181
182impl Semiapplicative for IdentityBrand {
183 #[hm_signature(Semiapplicative)]
190 #[doc_type_params(
194 "The lifetime of the values.",
195 "The brand of the cloneable function wrapper.",
196 "The type of the input value.",
197 "The type of the output value."
198 )]
199 #[doc_params("The identity containing the function.", "The identity containing the value.")]
203 fn apply<'a, FnBrand: 'a + CloneableFn, A: 'a + Clone, B: 'a>(
219 ff: Apply!(<Self as Kind!( type Of<'a, T: 'a>: 'a; )>::Of<'a, <FnBrand as CloneableFn>::Of<'a, A, B>>),
220 fa: Apply!(<Self as Kind!( type Of<'a, T: 'a>: 'a; )>::Of<'a, A>),
221 ) -> Apply!(<Self as Kind!( type Of<'a, T: 'a>: 'a; )>::Of<'a, B>) {
222 Identity(ff.0(fa.0))
223 }
224}
225
226impl Semimonad for IdentityBrand {
227 #[hm_signature(Semimonad)]
234 #[doc_type_params(
238 "The lifetime of the values.",
239 "The type of the result of the first computation.",
240 "The type of the result of the second computation.",
241 "The type of the function to apply."
242 )]
243 #[doc_params("The first identity.", "The function to apply to the value inside the identity.")]
247 fn bind<'a, A: 'a, B: 'a, Func>(
262 ma: Apply!(<Self as Kind!( type Of<'a, T: 'a>: 'a; )>::Of<'a, A>),
263 func: Func,
264 ) -> Apply!(<Self as Kind!( type Of<'a, T: 'a>: 'a; )>::Of<'a, B>)
265 where
266 Func: Fn(A) -> Apply!(<Self as Kind!( type Of<'a, T: 'a>: 'a; )>::Of<'a, B>) + 'a,
267 {
268 func(ma.0)
269 }
270}
271
272impl Foldable for IdentityBrand {
273 #[hm_signature(Foldable)]
280 #[doc_type_params(
284 "The lifetime of the values.",
285 "The brand of the cloneable function to use.",
286 "The type of the elements in the structure.",
287 "The type of the accumulator.",
288 "The type of the folding function."
289 )]
290 #[doc_params(
294 "The function to apply to each element and the accumulator.",
295 "The initial value of the accumulator.",
296 "The identity to fold."
297 )]
298 fn fold_right<'a, FnBrand, A: 'a, B: 'a, Func>(
313 func: Func,
314 initial: B,
315 fa: Apply!(<Self as Kind!( type Of<'a, T: 'a>: 'a; )>::Of<'a, A>),
316 ) -> B
317 where
318 Func: Fn(A, B) -> B + 'a,
319 FnBrand: CloneableFn + 'a,
320 {
321 func(fa.0, initial)
322 }
323
324 #[hm_signature(Foldable)]
331 #[doc_type_params(
335 "The lifetime of the values.",
336 "The brand of the cloneable function to use.",
337 "The type of the elements in the structure.",
338 "The type of the accumulator.",
339 "The type of the folding function."
340 )]
341 #[doc_params(
345 "The function to apply to the accumulator and each element.",
346 "The initial value of the accumulator.",
347 "The structure to fold."
348 )]
349 fn fold_left<'a, FnBrand, A: 'a, B: 'a, Func>(
364 func: Func,
365 initial: B,
366 fa: Apply!(<Self as Kind!( type Of<'a, T: 'a>: 'a; )>::Of<'a, A>),
367 ) -> B
368 where
369 Func: Fn(B, A) -> B + 'a,
370 FnBrand: CloneableFn + 'a,
371 {
372 func(initial, fa.0)
373 }
374
375 #[hm_signature(Foldable)]
382 #[doc_type_params(
386 "The lifetime of the values.",
387 "The brand of the cloneable function to use.",
388 "The type of the elements in the structure.",
389 "The type of the monoid.",
390 "The type of the mapping function."
391 )]
392 #[doc_params("The mapping function.", "The identity to fold.")]
396 fn fold_map<'a, FnBrand, A: 'a, M, Func>(
411 func: Func,
412 fa: Apply!(<Self as Kind!( type Of<'a, T: 'a>: 'a; )>::Of<'a, A>),
413 ) -> M
414 where
415 M: Monoid + 'a,
416 Func: Fn(A) -> M + 'a,
417 FnBrand: CloneableFn + 'a,
418 {
419 func(fa.0)
420 }
421}
422
423impl Traversable for IdentityBrand {
424 #[hm_signature(Traversable)]
431 #[doc_type_params(
435 "The lifetime of the values.",
436 "The type of the elements in the traversable structure.",
437 "The type of the elements in the resulting traversable structure.",
438 "The applicative context.",
439 "The type of the function to apply."
440 )]
441 #[doc_params(
445 "The function to apply to each element, returning a value in an applicative context.",
446 "The identity to traverse."
447 )]
448 fn traverse<'a, A: 'a + Clone, B: 'a + Clone, F: Applicative, Func>(
463 func: Func,
464 ta: Apply!(<Self as Kind!( type Of<'a, T: 'a>: 'a; )>::Of<'a, A>),
465 ) -> 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>)>)
466 where
467 Func: Fn(A) -> Apply!(<F as Kind!( type Of<'a, T: 'a>: 'a; )>::Of<'a, B>) + 'a,
468 Apply!(<Self as Kind!( type Of<'a, T: 'a>: 'a; )>::Of<'a, B>): Clone,
469 {
470 F::map(|b| Identity(b), func(ta.0))
471 }
472 #[hm_signature(Traversable)]
479 #[doc_type_params(
483 "The lifetime of the values.",
484 "The type of the elements in the traversable structure.",
485 "The applicative context."
486 )]
487 #[doc_params("The identity containing the applicative value.")]
491 fn sequence<'a, A: 'a + Clone, F: Applicative>(
506 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>)>)
507 ) -> 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>)>)
508 where
509 Apply!(<F as Kind!( type Of<'a, T: 'a>: 'a; )>::Of<'a, A>): Clone,
510 Apply!(<Self as Kind!( type Of<'a, T: 'a>: 'a; )>::Of<'a, A>): Clone,
511 {
512 F::map(|a| Identity(a), ta.0)
513 }
514}
515
516impl ParFoldable for IdentityBrand {
517 #[hm_signature(ParFoldable)]
524 #[doc_type_params(
528 "The lifetime of the values.",
529 "The brand of the cloneable function wrapper.",
530 "The element type.",
531 "The monoid type."
532 )]
533 #[doc_params("The mapping function.", "The identity to fold.")]
537 fn par_fold_map<'a, FnBrand, A, M>(
553 func: <FnBrand as SendCloneableFn>::SendOf<'a, A, M>,
554 fa: Apply!(<Self as Kind!( type Of<'a, T: 'a>: 'a; )>::Of<'a, A>),
555 ) -> M
556 where
557 FnBrand: 'a + SendCloneableFn,
558 A: 'a + Clone + Send + Sync,
559 M: Monoid + Send + Sync + 'a,
560 {
561 func(fa.0)
562 }
563
564 #[hm_signature(ParFoldable)]
571 #[doc_type_params(
575 "The lifetime of the values.",
576 "The brand of the cloneable function wrapper.",
577 "The element type.",
578 "The accumulator type."
579 )]
580 #[doc_params(
584 "The thread-safe function to apply to each element and the accumulator.",
585 "The initial value of the accumulator.",
586 "The identity to fold."
587 )]
588 fn par_fold_right<'a, FnBrand, A, B>(
604 func: <FnBrand as SendCloneableFn>::SendOf<'a, (A, B), B>,
605 initial: B,
606 fa: Apply!(<Self as Kind!( type Of<'a, T: 'a>: 'a; )>::Of<'a, A>),
607 ) -> B
608 where
609 FnBrand: 'a + SendCloneableFn,
610 A: 'a + Clone + Send + Sync,
611 B: Send + Sync + 'a,
612 {
613 func((fa.0, initial))
614 }
615}
616
617#[cfg(test)]
618mod tests {
619 use super::*;
620 use crate::{
621 brands::{OptionBrand, RcFnBrand},
622 classes::{functor::map, pointed::pure, semiapplicative::apply, semimonad::bind},
623 functions::{compose, identity},
624 };
625 use quickcheck_macros::quickcheck;
626
627 #[quickcheck]
631 fn functor_identity(x: i32) -> bool {
632 let x = Identity(x);
633 map::<IdentityBrand, _, _, _>(identity, x) == x
634 }
635
636 #[quickcheck]
638 fn functor_composition(x: i32) -> bool {
639 let x = Identity(x);
640 let f = |x: i32| x.wrapping_add(1);
641 let g = |x: i32| x.wrapping_mul(2);
642 map::<IdentityBrand, _, _, _>(compose(f, g), x)
643 == map::<IdentityBrand, _, _, _>(f, map::<IdentityBrand, _, _, _>(g, x))
644 }
645
646 #[quickcheck]
650 fn applicative_identity(v: i32) -> bool {
651 let v = Identity(v);
652 apply::<RcFnBrand, IdentityBrand, _, _>(
653 pure::<IdentityBrand, _>(<RcFnBrand as CloneableFn>::new(identity)),
654 v,
655 ) == v
656 }
657
658 #[quickcheck]
660 fn applicative_homomorphism(x: i32) -> bool {
661 let f = |x: i32| x.wrapping_mul(2);
662 apply::<RcFnBrand, IdentityBrand, _, _>(
663 pure::<IdentityBrand, _>(<RcFnBrand as CloneableFn>::new(f)),
664 pure::<IdentityBrand, _>(x),
665 ) == pure::<IdentityBrand, _>(f(x))
666 }
667
668 #[quickcheck]
670 fn applicative_composition(
671 w: i32,
672 u_val: i32,
673 v_val: i32,
674 ) -> bool {
675 let w = Identity(w);
676 let v_fn = move |x: i32| x.wrapping_mul(v_val);
677 let u_fn = move |x: i32| x.wrapping_add(u_val);
678
679 let v = pure::<IdentityBrand, _>(<RcFnBrand as CloneableFn>::new(v_fn));
680 let u = pure::<IdentityBrand, _>(<RcFnBrand as CloneableFn>::new(u_fn));
681
682 let vw = apply::<RcFnBrand, IdentityBrand, _, _>(v.clone(), w.clone());
684 let rhs = apply::<RcFnBrand, IdentityBrand, _, _>(u.clone(), vw);
685
686 let composed = move |x| u_fn(v_fn(x));
689 let uv = pure::<IdentityBrand, _>(<RcFnBrand as CloneableFn>::new(composed));
690
691 let lhs = apply::<RcFnBrand, IdentityBrand, _, _>(uv, w);
692
693 lhs == rhs
694 }
695
696 #[quickcheck]
698 fn applicative_interchange(y: i32) -> bool {
699 let f = |x: i32| x.wrapping_mul(2);
701 let u = pure::<IdentityBrand, _>(<RcFnBrand as CloneableFn>::new(f));
702
703 let lhs = apply::<RcFnBrand, IdentityBrand, _, _>(u.clone(), pure::<IdentityBrand, _>(y));
704
705 let rhs_fn =
706 <RcFnBrand as CloneableFn>::new(move |f: std::rc::Rc<dyn Fn(i32) -> i32>| f(y));
707 let rhs = apply::<RcFnBrand, IdentityBrand, _, _>(pure::<IdentityBrand, _>(rhs_fn), u);
708
709 lhs == rhs
710 }
711
712 #[quickcheck]
716 fn monad_left_identity(a: i32) -> bool {
717 let f = |x: i32| Identity(x.wrapping_mul(2));
718 bind::<IdentityBrand, _, _, _>(pure::<IdentityBrand, _>(a), f) == f(a)
719 }
720
721 #[quickcheck]
723 fn monad_right_identity(m: i32) -> bool {
724 let m = Identity(m);
725 bind::<IdentityBrand, _, _, _>(m, pure::<IdentityBrand, _>) == m
726 }
727
728 #[quickcheck]
730 fn monad_associativity(m: i32) -> bool {
731 let m = Identity(m);
732 let f = |x: i32| Identity(x.wrapping_mul(2));
733 let g = |x: i32| Identity(x.wrapping_add(1));
734 bind::<IdentityBrand, _, _, _>(bind::<IdentityBrand, _, _, _>(m, f), g)
735 == bind::<IdentityBrand, _, _, _>(m, |x| bind::<IdentityBrand, _, _, _>(f(x), g))
736 }
737
738 #[test]
742 fn map_test() {
743 assert_eq!(map::<IdentityBrand, _, _, _>(|x: i32| x + 1, Identity(1)), Identity(2));
744 }
745
746 #[test]
748 fn bind_test() {
749 assert_eq!(bind::<IdentityBrand, _, _, _>(Identity(1), |x| Identity(x + 1)), Identity(2));
750 }
751
752 #[test]
754 fn fold_right_test() {
755 assert_eq!(
756 crate::classes::foldable::fold_right::<RcFnBrand, IdentityBrand, _, _, _>(
757 |x: i32, acc| x + acc,
758 0,
759 Identity(1)
760 ),
761 1
762 );
763 }
764
765 #[test]
767 fn fold_left_test() {
768 assert_eq!(
769 crate::classes::foldable::fold_left::<RcFnBrand, IdentityBrand, _, _, _>(
770 |acc, x: i32| acc + x,
771 0,
772 Identity(1)
773 ),
774 1
775 );
776 }
777
778 #[test]
780 fn traverse_test() {
781 assert_eq!(
782 crate::classes::traversable::traverse::<IdentityBrand, _, _, OptionBrand, _>(
783 |x: i32| Some(x + 1),
784 Identity(1)
785 ),
786 Some(Identity(2))
787 );
788 }
789
790 #[test]
794 fn par_fold_map_test() {
795 use crate::{brands::*, functions::*};
796
797 let x = Identity(1);
798 let f = send_cloneable_fn_new::<ArcFnBrand, _, _>(|x: i32| x.to_string());
799 assert_eq!(par_fold_map::<ArcFnBrand, IdentityBrand, _, _>(f, x), "1".to_string());
800 }
801
802 #[test]
804 fn par_fold_right_test() {
805 use crate::{brands::*, functions::*};
806
807 let x = Identity(1);
808 let f = send_cloneable_fn_new::<ArcFnBrand, _, _>(|(a, b): (i32, i32)| a + b);
809 assert_eq!(par_fold_right::<ArcFnBrand, IdentityBrand, _, _>(f, 10, x), 11);
810 }
811}