1use crate::{
6 Apply,
7 brands::OptionBrand,
8 classes::{
9 Applicative, ApplyFirst, ApplySecond, CloneableFn, Compactable, Filterable, Foldable,
10 Functor, Lift, Monoid, ParFoldable, Pointed, Semiapplicative, Semimonad, SendCloneableFn,
11 Traversable, Witherable,
12 },
13 impl_kind,
14 kinds::*,
15 types::Pair,
16};
17use fp_macros::{doc_params, doc_type_params, hm_signature};
18
19impl_kind! {
20 for OptionBrand {
21 type Of<'a, A: 'a>: 'a = Option<A>;
22 }
23}
24
25impl Functor for OptionBrand {
26 #[hm_signature(Functor)]
33 #[doc_type_params(
37 "The lifetime of the value.",
38 "The type of the value inside the option.",
39 "The type of the result of applying the function.",
40 "The type of the function to apply."
41 )]
42 #[doc_params("The function to apply to the value.", "The option to map over.")]
46 fn map<'a, A: 'a, B: 'a, Func>(
61 func: Func,
62 fa: Apply!(<Self as Kind!( type Of<'a, T: 'a>: 'a; )>::Of<'a, A>),
63 ) -> Apply!(<Self as Kind!( type Of<'a, T: 'a>: 'a; )>::Of<'a, B>)
64 where
65 Func: Fn(A) -> B + 'a,
66 {
67 fa.map(func)
68 }
69}
70
71impl Lift for OptionBrand {
72 #[hm_signature(Lift)]
79 #[doc_type_params(
83 "The lifetime of the values.",
84 "The type of the first option's value.",
85 "The type of the second option's value.",
86 "The return type of the function.",
87 "The type of the binary function."
88 )]
89 #[doc_params("The binary function to apply.", "The first option.", "The second option.")]
93 fn lift2<'a, A, B, C, Func>(
109 func: Func,
110 fa: Apply!(<Self as Kind!( type Of<'a, T: 'a>: 'a; )>::Of<'a, A>),
111 fb: Apply!(<Self as Kind!( type Of<'a, T: 'a>: 'a; )>::Of<'a, B>),
112 ) -> Apply!(<Self as Kind!( type Of<'a, T: 'a>: 'a; )>::Of<'a, C>)
113 where
114 Func: Fn(A, B) -> C + 'a,
115 A: 'a,
116 B: 'a,
117 C: 'a,
118 {
119 fa.zip(fb).map(|(a, b)| func(a, b))
120 }
121}
122
123impl Pointed for OptionBrand {
124 #[hm_signature(Pointed)]
131 #[doc_type_params("The lifetime of the value.", "The type of the value to wrap.")]
135 #[doc_params("The value to wrap.")]
139 fn pure<'a, A: 'a>(a: A) -> Apply!(<Self as Kind!( type Of<'a, T: 'a>: 'a; )>::Of<'a, A>) {
154 Some(a)
155 }
156}
157
158impl ApplyFirst for OptionBrand {}
159impl ApplySecond for OptionBrand {}
160
161impl Semiapplicative for OptionBrand {
162 #[hm_signature(Semiapplicative)]
169 #[doc_type_params(
173 "The lifetime of the values.",
174 "The brand of the cloneable function wrapper.",
175 "The type of the input value.",
176 "The type of the output value."
177 )]
178 #[doc_params("The option containing the function.", "The option containing the value.")]
182 fn apply<'a, FnBrand: 'a + CloneableFn, A: 'a + Clone, B: 'a>(
198 ff: Apply!(<Self as Kind!( type Of<'a, T: 'a>: 'a; )>::Of<'a, <FnBrand as CloneableFn>::Of<'a, A, B>>),
199 fa: Apply!(<Self as Kind!( type Of<'a, T: 'a>: 'a; )>::Of<'a, A>),
200 ) -> Apply!(<Self as Kind!( type Of<'a, T: 'a>: 'a; )>::Of<'a, B>) {
201 match (ff, fa) {
202 (Some(f), Some(a)) => Some(f(a)),
203 _ => None,
204 }
205 }
206}
207
208impl Semimonad for OptionBrand {
209 #[hm_signature(Semimonad)]
216 #[doc_type_params(
220 "The lifetime of the values.",
221 "The type of the result of the first computation.",
222 "The type of the result of the second computation.",
223 "The type of the function to apply."
224 )]
225 #[doc_params("The first option.", "The function to apply to the value inside the option.")]
229 fn bind<'a, A: 'a, B: 'a, Func>(
245 ma: Apply!(<Self as Kind!( type Of<'a, T: 'a>: 'a; )>::Of<'a, A>),
246 func: Func,
247 ) -> Apply!(<Self as Kind!( type Of<'a, T: 'a>: 'a; )>::Of<'a, B>)
248 where
249 Func: Fn(A) -> Apply!(<Self as Kind!( type Of<'a, T: 'a>: 'a; )>::Of<'a, B>) + 'a,
250 {
251 ma.and_then(func)
252 }
253}
254
255impl Foldable for OptionBrand {
256 #[hm_signature(Foldable)]
263 #[doc_type_params(
267 "The lifetime of the values.",
268 "The brand of the cloneable function to use.",
269 "The type of the elements in the structure.",
270 "The type of the accumulator.",
271 "The type of the folding function."
272 )]
273 #[doc_params("The folding function.", "The initial value.", "The option to fold.")]
277 fn fold_right<'a, FnBrand, A: 'a, B: 'a, Func>(
292 func: Func,
293 initial: B,
294 fa: Apply!(<Self as Kind!( type Of<'a, T: 'a>: 'a; )>::Of<'a, A>),
295 ) -> B
296 where
297 Func: Fn(A, B) -> B + 'a,
298 FnBrand: CloneableFn + 'a,
299 {
300 match fa {
301 Some(a) => func(a, initial),
302 None => initial,
303 }
304 }
305
306 #[hm_signature(Foldable)]
313 #[doc_type_params(
317 "The lifetime of the values.",
318 "The brand of the cloneable function to use.",
319 "The type of the elements in the structure.",
320 "The type of the accumulator.",
321 "The type of the folding function."
322 )]
323 #[doc_params(
327 "The function to apply to the accumulator and each element.",
328 "The initial value of the accumulator.",
329 "The option to fold."
330 )]
331 fn fold_left<'a, FnBrand, A: 'a, B: 'a, Func>(
346 func: Func,
347 initial: B,
348 fa: Apply!(<Self as Kind!( type Of<'a, T: 'a>: 'a; )>::Of<'a, A>),
349 ) -> B
350 where
351 Func: Fn(B, A) -> B + 'a,
352 FnBrand: CloneableFn + 'a,
353 {
354 match fa {
355 Some(a) => func(initial, a),
356 None => initial,
357 }
358 }
359
360 #[hm_signature(Foldable)]
367 #[doc_type_params(
371 "The lifetime of the values.",
372 "The brand of the cloneable function to use.",
373 "The type of the elements in the structure.",
374 "The type of the monoid.",
375 "The type of the mapping function."
376 )]
377 #[doc_params("The mapping function.", "The option to fold.")]
381 fn fold_map<'a, FnBrand, A: 'a, M, Func>(
396 func: Func,
397 fa: Apply!(<Self as Kind!( type Of<'a, T: 'a>: 'a; )>::Of<'a, A>),
398 ) -> M
399 where
400 M: Monoid + 'a,
401 Func: Fn(A) -> M + 'a,
402 FnBrand: CloneableFn + 'a,
403 {
404 match fa {
405 Some(a) => func(a),
406 None => M::empty(),
407 }
408 }
409}
410
411impl Traversable for OptionBrand {
412 #[hm_signature(Traversable)]
419 #[doc_type_params(
423 "The lifetime of the values.",
424 "The type of the elements in the traversable structure.",
425 "The type of the elements in the resulting traversable structure.",
426 "The applicative context.",
427 "The type of the function to apply."
428 )]
429 #[doc_params(
433 "The function to apply to each element, returning a value in an applicative context.",
434 "The option to traverse."
435 )]
436 fn traverse<'a, A: 'a + Clone, B: 'a + Clone, F: Applicative, Func>(
452 func: Func,
453 ta: Apply!(<Self as Kind!( type Of<'a, T: 'a>: 'a; )>::Of<'a, A>),
454 ) -> 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>)>)
455 where
456 Func: Fn(A) -> Apply!(<F as Kind!( type Of<'a, T: 'a>: 'a; )>::Of<'a, B>) + 'a,
457 Apply!(<Self as Kind!( type Of<'a, T: 'a>: 'a; )>::Of<'a, B>): Clone,
458 {
459 match ta {
460 Some(a) => F::map(|b| Some(b), func(a)),
461 None => F::pure(None),
462 }
463 }
464 #[hm_signature(Traversable)]
471 #[doc_type_params(
475 "The lifetime of the values.",
476 "The type of the elements in the traversable structure.",
477 "The applicative context."
478 )]
479 #[doc_params("The option containing the applicative value.")]
483 fn sequence<'a, A: 'a + Clone, F: Applicative>(
499 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>)>)
500 ) -> 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>)>)
501 where
502 Apply!(<F as Kind!( type Of<'a, T: 'a>: 'a; )>::Of<'a, A>): Clone,
503 Apply!(<Self as Kind!( type Of<'a, T: 'a>: 'a; )>::Of<'a, A>): Clone,
504 {
505 match ta {
506 Some(fa) => F::map(|a| Some(a), fa),
507 None => F::pure(None),
508 }
509 }
510}
511
512impl ParFoldable for OptionBrand {
513 #[hm_signature(ParFoldable)]
520 #[doc_type_params(
524 "The lifetime of the values.",
525 "The brand of the cloneable function wrapper.",
526 "The element type.",
527 "The monoid type."
528 )]
529 #[doc_params("The mapping function.", "The option to fold.")]
533 fn par_fold_map<'a, FnBrand, A, M>(
549 func: <FnBrand as SendCloneableFn>::SendOf<'a, A, M>,
550 fa: Apply!(<Self as Kind!( type Of<'a, T: 'a>: 'a; )>::Of<'a, A>),
551 ) -> M
552 where
553 FnBrand: 'a + SendCloneableFn,
554 A: 'a + Clone + Send + Sync,
555 M: Monoid + Send + Sync + 'a,
556 {
557 match fa {
558 Some(a) => func(a),
559 None => M::empty(),
560 }
561 }
562}
563
564impl Compactable for OptionBrand {
565 #[hm_signature(Compactable)]
572 #[doc_type_params("The lifetime of the values.", "The type of the elements.")]
576 #[doc_params("The nested option.")]
580 fn compact<'a, A: 'a>(
596 fa: Apply!(<Self as Kind!( type Of<'a, T: 'a>: 'a; )>::Of<
597 'a,
598 Apply!(<OptionBrand as Kind!( type Of<'a, T: 'a>: 'a; )>::Of<'a, A>),
599 >)
600 ) -> Apply!(<Self as Kind!( type Of<'a, T: 'a>: 'a; )>::Of<'a, A>) {
601 fa.flatten()
602 }
603
604 #[hm_signature(Compactable)]
611 #[doc_type_params(
615 "The lifetime of the values.",
616 "The type of the success value.",
617 "The type of the error value."
618 )]
619 #[doc_params("The option of result.")]
623 fn separate<'a, O: 'a, E: 'a>(
639 fa: Apply!(<Self as Kind!( type Of<'a, T: 'a>: 'a; )>::Of<'a, Result<O, E>>)
640 ) -> Pair<
641 Apply!(<Self as Kind!( type Of<'a, T: 'a>: 'a; )>::Of<'a, O>),
642 Apply!(<Self as Kind!( type Of<'a, T: 'a>: 'a; )>::Of<'a, E>),
643 > {
644 match fa {
645 Some(Ok(o)) => Pair(Some(o), None),
646 Some(Err(e)) => Pair(None, Some(e)),
647 None => Pair(None, None),
648 }
649 }
650}
651
652impl Filterable for OptionBrand {
653 #[hm_signature(Filterable)]
660 #[doc_type_params(
664 "The lifetime of the values.",
665 "The type of the input value.",
666 "The type of the success value.",
667 "The type of the error value.",
668 "The type of the function to apply."
669 )]
670 #[doc_params("The function to apply.", "The option to partition.")]
674 fn partition_map<'a, A: 'a, O: 'a, E: 'a, Func>(
690 func: Func,
691 fa: Apply!(<Self as Kind!( type Of<'a, T: 'a>: 'a; )>::Of<'a, A>),
692 ) -> Pair<
693 Apply!(<Self as Kind!( type Of<'a, T: 'a>: 'a; )>::Of<'a, O>),
694 Apply!(<Self as Kind!( type Of<'a, T: 'a>: 'a; )>::Of<'a, E>),
695 >
696 where
697 Func: Fn(A) -> Result<O, E> + 'a,
698 {
699 match fa {
700 Some(a) => match func(a) {
701 Ok(o) => Pair(Some(o), None),
702 Err(e) => Pair(None, Some(e)),
703 },
704 None => Pair(None, None),
705 }
706 }
707 #[hm_signature(Filterable)]
714 #[doc_type_params(
718 "The lifetime of the values.",
719 "The type of the elements.",
720 "The type of the predicate."
721 )]
722 #[doc_params("The predicate.", "The option to partition.")]
726 fn partition<'a, A: 'a + Clone, Func>(
742 func: Func,
743 fa: Apply!(<Self as Kind!( type Of<'a, T: 'a>: 'a; )>::Of<'a, A>),
744 ) -> Pair<
745 Apply!(<Self as Kind!( type Of<'a, T: 'a>: 'a; )>::Of<'a, A>),
746 Apply!(<Self as Kind!( type Of<'a, T: 'a>: 'a; )>::Of<'a, A>),
747 >
748 where
749 Func: Fn(A) -> bool + 'a,
750 {
751 match fa {
752 Some(a) => {
753 if func(a.clone()) {
754 Pair(Some(a), None)
755 } else {
756 Pair(None, Some(a))
757 }
758 }
759 None => Pair(None, None),
760 }
761 }
762
763 #[hm_signature(Filterable)]
770 #[doc_type_params(
774 "The lifetime of the values.",
775 "The type of the input value.",
776 "The type of the result of applying the function.",
777 "The type of the function to apply."
778 )]
779 #[doc_params("The function to apply.", "The option to filter and map.")]
783 fn filter_map<'a, A: 'a, B: 'a, Func>(
799 func: Func,
800 fa: Apply!(<Self as Kind!( type Of<'a, T: 'a>: 'a; )>::Of<'a, A>),
801 ) -> Apply!(<Self as Kind!( type Of<'a, T: 'a>: 'a; )>::Of<'a, B>)
802 where
803 Func: Fn(A) -> Option<B> + 'a,
804 {
805 fa.and_then(func)
806 }
807
808 #[hm_signature(Filterable)]
815 #[doc_type_params(
819 "The lifetime of the values.",
820 "The type of the elements.",
821 "The type of the predicate."
822 )]
823 #[doc_params("The predicate.", "The option to filter.")]
827 fn filter<'a, A: 'a + Clone, Func>(
843 func: Func,
844 fa: Apply!(<Self as Kind!( type Of<'a, T: 'a>: 'a; )>::Of<'a, A>),
845 ) -> Apply!(<Self as Kind!( type Of<'a, T: 'a>: 'a; )>::Of<'a, A>)
846 where
847 Func: Fn(A) -> bool + 'a,
848 {
849 fa.filter(|a| func(a.clone()))
850 }
851}
852
853impl Witherable for OptionBrand {
854 #[hm_signature(Witherable)]
861 #[doc_type_params(
865 "The lifetime of the values.",
866 "The applicative context.",
867 "The type of the elements in the input structure.",
868 "The type of the success values.",
869 "The type of the error values.",
870 "The type of the function to apply."
871 )]
872 #[doc_params(
876 "The function to apply to each element, returning a `Result` in an applicative context.",
877 "The option to partition."
878 )]
879 fn wilt<'a, M: Applicative, A: 'a + Clone, O: 'a + Clone, E: 'a + Clone, Func>(
894 func: Func,
895 ta: Apply!(<Self as Kind!( type Of<'a, T: 'a>: 'a; )>::Of<'a, A>),
896 ) -> Apply!(<M as Kind!( type Of<'a, T: 'a>: 'a; )>::Of<
897 'a,
898 Pair<
899 Apply!(<Self as Kind!( type Of<'a, T: 'a>: 'a; )>::Of<'a, O>),
900 Apply!(<Self as Kind!( type Of<'a, T: 'a>: 'a; )>::Of<'a, E>),
901 >,
902 >)
903 where
904 Func: Fn(A) -> Apply!(<M as Kind!( type Of<'a, T: 'a>: 'a; )>::Of<'a, Result<O, E>>) + 'a,
905 Apply!(<Self as Kind!( type Of<'a, T: 'a>: 'a; )>::Of<'a, Result<O, E>>): Clone,
906 Apply!(<M as Kind!( type Of<'a, T: 'a>: 'a; )>::Of<'a, Result<O, E>>): Clone,
907 {
908 match ta {
909 Some(a) => M::map(
910 |res| match res {
911 Ok(o) => Pair(Some(o), None),
912 Err(e) => Pair(None, Some(e)),
913 },
914 func(a),
915 ),
916 None => M::pure(Pair(None, None)),
917 }
918 }
919
920 #[hm_signature(Witherable)]
927 #[doc_type_params(
931 "The lifetime of the values.",
932 "The applicative context.",
933 "The type of the elements in the input structure.",
934 "The type of the result of applying the function.",
935 "The type of the function to apply."
936 )]
937 #[doc_params(
941 "The function to apply to each element, returning an `Option` in an applicative context.",
942 "The option to filter and map."
943 )]
944 fn wither<'a, M: Applicative, A: 'a + Clone, B: 'a + Clone, Func>(
959 func: Func,
960 ta: Apply!(<Self as Kind!( type Of<'a, T: 'a>: 'a; )>::Of<'a, A>),
961 ) -> Apply!(<M as Kind!( type Of<'a, T: 'a>: 'a; )>::Of<
962 'a,
963 Apply!(<Self as Kind!( type Of<'a, T: 'a>: 'a; )>::Of<'a, B>),
964 >)
965 where
966 Func: Fn(A) -> Apply!(<M as Kind!( type Of<'a, T: 'a>: 'a; )>::Of<'a, Option<B>>) + 'a,
967 Apply!(<Self as Kind!( type Of<'a, T: 'a>: 'a; )>::Of<'a, Option<B>>): Clone,
968 Apply!(<M as Kind!( type Of<'a, T: 'a>: 'a; )>::Of<'a, Option<B>>): Clone,
969 {
970 match ta {
971 Some(a) => func(a),
972 None => M::pure(None),
973 }
974 }
975}
976
977#[cfg(test)]
978mod tests {
979 use super::*;
980 use crate::{brands::*, functions::*};
981 use quickcheck_macros::quickcheck;
982
983 #[quickcheck]
987 fn functor_identity(x: Option<i32>) -> bool {
988 map::<OptionBrand, _, _, _>(identity, x) == x
989 }
990
991 #[quickcheck]
993 fn functor_composition(x: Option<i32>) -> bool {
994 let f = |x: i32| x.wrapping_add(1);
995 let g = |x: i32| x.wrapping_mul(2);
996 map::<OptionBrand, _, _, _>(compose(f, g), x)
997 == map::<OptionBrand, _, _, _>(f, map::<OptionBrand, _, _, _>(g, x))
998 }
999
1000 #[quickcheck]
1004 fn applicative_identity(v: Option<i32>) -> bool {
1005 apply::<RcFnBrand, OptionBrand, _, _>(
1006 pure::<OptionBrand, _>(<RcFnBrand as CloneableFn>::new(identity)),
1007 v,
1008 ) == v
1009 }
1010
1011 #[quickcheck]
1013 fn applicative_homomorphism(x: i32) -> bool {
1014 let f = |x: i32| x.wrapping_mul(2);
1015 apply::<RcFnBrand, OptionBrand, _, _>(
1016 pure::<OptionBrand, _>(<RcFnBrand as CloneableFn>::new(f)),
1017 pure::<OptionBrand, _>(x),
1018 ) == pure::<OptionBrand, _>(f(x))
1019 }
1020
1021 #[quickcheck]
1023 fn applicative_composition(
1024 w: Option<i32>,
1025 u_is_some: bool,
1026 v_is_some: bool,
1027 ) -> bool {
1028 let v_fn = |x: i32| x.wrapping_mul(2);
1029 let u_fn = |x: i32| x.wrapping_add(1);
1030
1031 let v = if v_is_some {
1032 pure::<OptionBrand, _>(<RcFnBrand as CloneableFn>::new(v_fn))
1033 } else {
1034 None
1035 };
1036 let u = if u_is_some {
1037 pure::<OptionBrand, _>(<RcFnBrand as CloneableFn>::new(u_fn))
1038 } else {
1039 None
1040 };
1041
1042 let vw = apply::<RcFnBrand, OptionBrand, _, _>(v.clone(), w.clone());
1044 let rhs = apply::<RcFnBrand, OptionBrand, _, _>(u.clone(), vw);
1045
1046 let uv = match (u, v) {
1049 (Some(uf), Some(vf)) => {
1050 let composed = move |x| uf(vf(x));
1051 Some(<RcFnBrand as CloneableFn>::new(composed))
1052 }
1053 _ => None,
1054 };
1055
1056 let lhs = apply::<RcFnBrand, OptionBrand, _, _>(uv, w);
1057
1058 lhs == rhs
1059 }
1060
1061 #[quickcheck]
1063 fn applicative_interchange(y: i32) -> bool {
1064 let f = |x: i32| x.wrapping_mul(2);
1066 let u = pure::<OptionBrand, _>(<RcFnBrand as CloneableFn>::new(f));
1067
1068 let lhs = apply::<RcFnBrand, OptionBrand, _, _>(u.clone(), pure::<OptionBrand, _>(y));
1069
1070 let rhs_fn =
1071 <RcFnBrand as CloneableFn>::new(move |f: std::rc::Rc<dyn Fn(i32) -> i32>| f(y));
1072 let rhs = apply::<RcFnBrand, OptionBrand, _, _>(pure::<OptionBrand, _>(rhs_fn), u);
1073
1074 lhs == rhs
1075 }
1076
1077 #[quickcheck]
1081 fn monad_left_identity(a: i32) -> bool {
1082 let f = |x: i32| Some(x.wrapping_mul(2));
1083 bind::<OptionBrand, _, _, _>(pure::<OptionBrand, _>(a), f) == f(a)
1084 }
1085
1086 #[quickcheck]
1088 fn monad_right_identity(m: Option<i32>) -> bool {
1089 bind::<OptionBrand, _, _, _>(m, pure::<OptionBrand, _>) == m
1090 }
1091
1092 #[quickcheck]
1094 fn monad_associativity(m: Option<i32>) -> bool {
1095 let f = |x: i32| Some(x.wrapping_mul(2));
1096 let g = |x: i32| Some(x.wrapping_add(1));
1097 bind::<OptionBrand, _, _, _>(bind::<OptionBrand, _, _, _>(m, f), g)
1098 == bind::<OptionBrand, _, _, _>(m, |x| bind::<OptionBrand, _, _, _>(f(x), g))
1099 }
1100
1101 #[test]
1105 fn map_none() {
1106 assert_eq!(map::<OptionBrand, _, _, _>(|x: i32| x + 1, None), None);
1107 }
1108
1109 #[test]
1111 fn bind_none() {
1112 assert_eq!(bind::<OptionBrand, _, _, _>(None, |x: i32| Some(x + 1)), None);
1113 }
1114
1115 #[test]
1117 fn bind_returning_none() {
1118 assert_eq!(bind::<OptionBrand, _, _, _>(Some(5), |_| None::<i32>), None);
1119 }
1120
1121 #[test]
1123 fn fold_right_none() {
1124 assert_eq!(
1125 crate::classes::foldable::fold_right::<RcFnBrand, OptionBrand, _, _, _>(
1126 |x: i32, acc| x + acc,
1127 0,
1128 None
1129 ),
1130 0
1131 );
1132 }
1133
1134 #[test]
1136 fn fold_left_none() {
1137 assert_eq!(
1138 crate::classes::foldable::fold_left::<RcFnBrand, OptionBrand, _, _, _>(
1139 |acc, x: i32| acc + x,
1140 0,
1141 None
1142 ),
1143 0
1144 );
1145 }
1146
1147 #[test]
1149 fn traverse_none() {
1150 assert_eq!(
1151 crate::classes::traversable::traverse::<OptionBrand, _, _, OptionBrand, _>(
1152 |x: i32| Some(x + 1),
1153 None
1154 ),
1155 Some(None)
1156 );
1157 }
1158
1159 #[test]
1161 fn traverse_returning_none() {
1162 assert_eq!(
1163 crate::classes::traversable::traverse::<OptionBrand, _, _, OptionBrand, _>(
1164 |_: i32| None::<i32>,
1165 Some(5)
1166 ),
1167 None
1168 );
1169 }
1170
1171 #[test]
1175 fn par_fold_map_none() {
1176 let x: Option<i32> = None;
1177 let f = send_cloneable_fn_new::<ArcFnBrand, _, _>(|x: i32| x.to_string());
1178 assert_eq!(par_fold_map::<ArcFnBrand, OptionBrand, _, _>(f, x), "".to_string());
1179 }
1180
1181 #[test]
1183 fn par_fold_map_some() {
1184 let x = Some(5);
1185 let f = send_cloneable_fn_new::<ArcFnBrand, _, _>(|x: i32| x.to_string());
1186 assert_eq!(par_fold_map::<ArcFnBrand, OptionBrand, _, _>(f, x), "5".to_string());
1187 }
1188
1189 #[test]
1191 fn par_fold_right_some() {
1192 let x = Some(5);
1193 let f = send_cloneable_fn_new::<ArcFnBrand, _, _>(|(a, b): (i32, i32)| a + b);
1194 assert_eq!(par_fold_right::<ArcFnBrand, OptionBrand, _, _>(f, 10, x), 15);
1195 }
1196
1197 #[quickcheck]
1201 fn filterable_filter_map_identity(x: Option<Option<i32>>) -> bool {
1202 filter_map::<OptionBrand, _, _, _>(identity, x.clone()) == compact::<OptionBrand, _>(x)
1203 }
1204
1205 #[quickcheck]
1207 fn filterable_filter_map_just(x: Option<i32>) -> bool {
1208 filter_map::<OptionBrand, _, _, _>(Some, x.clone()) == x
1209 }
1210
1211 #[quickcheck]
1213 fn filterable_filter_map_composition(x: Option<i32>) -> bool {
1214 let r = |i: i32| if i % 2 == 0 { Some(i) } else { None };
1215 let l = |i: i32| if i > 5 { Some(i) } else { None };
1216 let composed = |i| r(i).and_then(l);
1217
1218 filter_map::<OptionBrand, _, _, _>(composed, x.clone())
1219 == filter_map::<OptionBrand, _, _, _>(l, filter_map::<OptionBrand, _, _, _>(r, x))
1220 }
1221
1222 #[quickcheck]
1224 fn filterable_filter_consistency(x: Option<i32>) -> bool {
1225 let p = |i: i32| i % 2 == 0;
1226 let maybe_bool = |i| if p(i) { Some(i) } else { None };
1227
1228 filter::<OptionBrand, _, _>(p, x.clone())
1229 == filter_map::<OptionBrand, _, _, _>(maybe_bool, x)
1230 }
1231
1232 #[quickcheck]
1234 fn filterable_partition_map_identity(x: Option<Result<i32, i32>>) -> bool {
1235 partition_map::<OptionBrand, _, _, _, _>(identity, x.clone())
1236 == separate::<OptionBrand, _, _>(x)
1237 }
1238
1239 #[quickcheck]
1241 fn filterable_partition_map_right_identity(x: Option<i32>) -> bool {
1242 let Pair(oks, _) = partition_map::<OptionBrand, _, _, _, _>(Ok::<_, i32>, x.clone());
1243 oks == x
1244 }
1245
1246 #[quickcheck]
1248 fn filterable_partition_map_left_identity(x: Option<i32>) -> bool {
1249 let Pair(_, errs) = partition_map::<OptionBrand, _, _, _, _>(Err::<i32, _>, x.clone());
1250 errs == x
1251 }
1252
1253 #[quickcheck]
1255 fn filterable_partition_consistency(x: Option<i32>) -> bool {
1256 let p = |i: i32| i % 2 == 0;
1257 let either_bool = |i| if p(i) { Ok(i) } else { Err(i) };
1258
1259 let Pair(satisfied, not_satisfied) = partition::<OptionBrand, _, _>(p, x.clone());
1260 let Pair(oks, errs) = partition_map::<OptionBrand, _, _, _, _>(either_bool, x);
1261
1262 satisfied == oks && not_satisfied == errs
1263 }
1264
1265 #[quickcheck]
1269 fn witherable_identity(x: Option<i32>) -> bool {
1270 wither::<OptionBrand, OptionBrand, _, _, _>(|i| Some(Some(i)), x.clone()) == Some(x)
1271 }
1272
1273 #[quickcheck]
1275 fn witherable_wilt_consistency(x: Option<i32>) -> bool {
1276 let p = |i: i32| Some(if i % 2 == 0 { Ok(i) } else { Err(i) });
1277
1278 let lhs = wilt::<OptionBrand, OptionBrand, _, _, _, _>(p, x.clone());
1279 let rhs = map::<OptionBrand, _, _, _>(
1280 |res| separate::<OptionBrand, _, _>(res),
1281 traverse::<OptionBrand, _, _, OptionBrand, _>(p, x),
1282 );
1283
1284 lhs == rhs
1285 }
1286
1287 #[quickcheck]
1289 fn witherable_wither_consistency(x: Option<i32>) -> bool {
1290 let p = |i: i32| Some(if i % 2 == 0 { Some(i) } else { None });
1291
1292 let lhs = wither::<OptionBrand, OptionBrand, _, _, _>(p, x.clone());
1293 let rhs = map::<OptionBrand, _, _, _>(
1294 |opt| compact::<OptionBrand, _>(opt),
1295 traverse::<OptionBrand, _, _, OptionBrand, _>(p, x),
1296 );
1297
1298 lhs == rhs
1299 }
1300
1301 #[test]
1305 fn compact_some_none() {
1306 assert_eq!(compact::<OptionBrand, _>(Some(None::<i32>)), None);
1307 }
1308
1309 #[test]
1311 fn compact_some_some() {
1312 assert_eq!(compact::<OptionBrand, _>(Some(Some(5))), Some(5));
1313 }
1314
1315 #[test]
1317 fn compact_none() {
1318 assert_eq!(compact::<OptionBrand, _>(None::<Option<i32>>), None);
1319 }
1320
1321 #[test]
1323 fn separate_some_ok() {
1324 let Pair(oks, errs) = separate::<OptionBrand, _, _>(Some(Ok::<i32, &str>(5)));
1325 assert_eq!(oks, Some(5));
1326 assert_eq!(errs, None);
1327 }
1328
1329 #[test]
1331 fn separate_some_err() {
1332 let Pair(oks, errs) = separate::<OptionBrand, _, _>(Some(Err::<i32, &str>("error")));
1333 assert_eq!(oks, None);
1334 assert_eq!(errs, Some("error"));
1335 }
1336
1337 #[test]
1339 fn separate_none() {
1340 let Pair(oks, errs) = separate::<OptionBrand, _, _>(None::<Result<i32, &str>>);
1341 assert_eq!(oks, None);
1342 assert_eq!(errs, None);
1343 }
1344
1345 #[test]
1347 fn partition_map_none() {
1348 let Pair(oks, errs) =
1349 partition_map::<OptionBrand, _, _, _, _>(|x: i32| Ok::<i32, i32>(x), None::<i32>);
1350 assert_eq!(oks, None);
1351 assert_eq!(errs, None);
1352 }
1353
1354 #[test]
1356 fn partition_none() {
1357 let Pair(satisfied, not_satisfied) =
1358 partition::<OptionBrand, _, _>(|x: i32| x > 0, None::<i32>);
1359 assert_eq!(satisfied, None);
1360 assert_eq!(not_satisfied, None);
1361 }
1362
1363 #[test]
1365 fn filter_map_none() {
1366 assert_eq!(filter_map::<OptionBrand, _, _, _>(|x: i32| Some(x), None::<i32>), None);
1367 }
1368
1369 #[test]
1371 fn filter_none() {
1372 assert_eq!(filter::<OptionBrand, _, _>(|x: i32| x > 0, None::<i32>), None);
1373 }
1374
1375 #[test]
1377 fn wilt_none() {
1378 let res = wilt::<OptionBrand, OptionBrand, _, _, _, _>(
1379 |x: i32| Some(Ok::<i32, i32>(x)),
1380 None::<i32>,
1381 );
1382 assert_eq!(res, Some(Pair(None, None)));
1383 }
1384
1385 #[test]
1387 fn wither_none() {
1388 let res = wither::<OptionBrand, OptionBrand, _, _, _>(|x: i32| Some(Some(x)), None::<i32>);
1389 assert_eq!(res, Some(None));
1390 }
1391}