1#[fp_macros::document_module]
6mod inner {
7 use crate::{
8 Apply,
9 brands::OptionBrand,
10 classes::{
11 Applicative, ApplyFirst, ApplySecond, CloneableFn, Compactable, Filterable, Foldable,
12 Functor, Lift, Monoid, ParFoldable, Pointed, Semiapplicative, Semimonad,
13 SendCloneableFn, Traversable, Witherable,
14 },
15 impl_kind,
16 kinds::*,
17 };
18 use fp_macros::document_parameters;
19
20 impl_kind! {
21 for OptionBrand {
22 type Of<'a, A: 'a>: 'a = Option<A>;
23 }
24 }
25
26 impl Functor for OptionBrand {
27 #[document_signature]
34 #[document_type_parameters(
38 "The lifetime of the value.",
39 "The type of the value inside the option.",
40 "The type of the result of applying the function.",
41 "The type of the function to apply."
42 )]
43 #[document_parameters("The function to apply to the value.", "The option to map over.")]
47 fn map<'a, A: 'a, B: 'a, Func>(
62 func: Func,
63 fa: Apply!(<Self as Kind!( type Of<'a, T: 'a>: 'a; )>::Of<'a, A>),
64 ) -> Apply!(<Self as Kind!( type Of<'a, T: 'a>: 'a; )>::Of<'a, B>)
65 where
66 Func: Fn(A) -> B + 'a,
67 {
68 fa.map(func)
69 }
70 }
71
72 impl Lift for OptionBrand {
73 #[document_signature]
80 #[document_type_parameters(
84 "The lifetime of the values.",
85 "The type of the first option's value.",
86 "The type of the second option's value.",
87 "The return type of the function.",
88 "The type of the binary function."
89 )]
90 #[document_parameters(
94 "The binary function to apply.",
95 "The first option.",
96 "The second option."
97 )]
98 fn lift2<'a, A, B, C, Func>(
114 func: Func,
115 fa: Apply!(<Self as Kind!( type Of<'a, T: 'a>: 'a; )>::Of<'a, A>),
116 fb: Apply!(<Self as Kind!( type Of<'a, T: 'a>: 'a; )>::Of<'a, B>),
117 ) -> Apply!(<Self as Kind!( type Of<'a, T: 'a>: 'a; )>::Of<'a, C>)
118 where
119 Func: Fn(A, B) -> C + 'a,
120 A: 'a,
121 B: 'a,
122 C: 'a,
123 {
124 fa.zip(fb).map(|(a, b)| func(a, b))
125 }
126 }
127
128 impl Pointed for OptionBrand {
129 #[document_signature]
136 #[document_type_parameters("The lifetime of the value.", "The type of the value to wrap.")]
140 #[document_parameters("The value to wrap.")]
144 fn pure<'a, A: 'a>(a: A) -> Apply!(<Self as Kind!( type Of<'a, T: 'a>: 'a; )>::Of<'a, A>) {
159 Some(a)
160 }
161 }
162
163 impl ApplyFirst for OptionBrand {}
164 impl ApplySecond for OptionBrand {}
165
166 impl Semiapplicative for OptionBrand {
167 #[document_signature]
174 #[document_type_parameters(
178 "The lifetime of the values.",
179 "The brand of the cloneable function wrapper.",
180 "The type of the input value.",
181 "The type of the output value."
182 )]
183 #[document_parameters(
187 "The option containing the function.",
188 "The option containing the value."
189 )]
190 fn apply<'a, FnBrand: 'a + CloneableFn, A: 'a + Clone, B: 'a>(
206 ff: Apply!(<Self as Kind!( type Of<'a, T: 'a>: 'a; )>::Of<'a, <FnBrand as CloneableFn>::Of<'a, A, B>>),
207 fa: Apply!(<Self as Kind!( type Of<'a, T: 'a>: 'a; )>::Of<'a, A>),
208 ) -> Apply!(<Self as Kind!( type Of<'a, T: 'a>: 'a; )>::Of<'a, B>) {
209 match (ff, fa) {
210 (Some(f), Some(a)) => Some(f(a)),
211 _ => None,
212 }
213 }
214 }
215
216 impl Semimonad for OptionBrand {
217 #[document_signature]
224 #[document_type_parameters(
228 "The lifetime of the values.",
229 "The type of the result of the first computation.",
230 "The type of the result of the second computation.",
231 "The type of the function to apply."
232 )]
233 #[document_parameters(
237 "The first option.",
238 "The function to apply to the value inside the option."
239 )]
240 fn bind<'a, A: 'a, B: 'a, Func>(
256 ma: Apply!(<Self as Kind!( type Of<'a, T: 'a>: 'a; )>::Of<'a, A>),
257 func: Func,
258 ) -> Apply!(<Self as Kind!( type Of<'a, T: 'a>: 'a; )>::Of<'a, B>)
259 where
260 Func: Fn(A) -> Apply!(<Self as Kind!( type Of<'a, T: 'a>: 'a; )>::Of<'a, B>) + 'a,
261 {
262 ma.and_then(func)
263 }
264 }
265
266 impl Foldable for OptionBrand {
267 #[document_signature]
274 #[document_type_parameters(
278 "The lifetime of the values.",
279 "The brand of the cloneable function to use.",
280 "The type of the elements in the structure.",
281 "The type of the accumulator.",
282 "The type of the folding function."
283 )]
284 #[document_parameters("The folding function.", "The initial value.", "The option to fold.")]
288 fn fold_right<'a, FnBrand, A: 'a, B: 'a, Func>(
303 func: Func,
304 initial: B,
305 fa: Apply!(<Self as Kind!( type Of<'a, T: 'a>: 'a; )>::Of<'a, A>),
306 ) -> B
307 where
308 Func: Fn(A, B) -> B + 'a,
309 FnBrand: CloneableFn + 'a,
310 {
311 match fa {
312 Some(a) => func(a, initial),
313 None => initial,
314 }
315 }
316
317 #[document_signature]
324 #[document_type_parameters(
328 "The lifetime of the values.",
329 "The brand of the cloneable function to use.",
330 "The type of the elements in the structure.",
331 "The type of the accumulator.",
332 "The type of the folding function."
333 )]
334 #[document_parameters(
338 "The function to apply to the accumulator and each element.",
339 "The initial value of the accumulator.",
340 "The option to fold."
341 )]
342 fn fold_left<'a, FnBrand, A: 'a, B: 'a, Func>(
357 func: Func,
358 initial: B,
359 fa: Apply!(<Self as Kind!( type Of<'a, T: 'a>: 'a; )>::Of<'a, A>),
360 ) -> B
361 where
362 Func: Fn(B, A) -> B + 'a,
363 FnBrand: CloneableFn + 'a,
364 {
365 match fa {
366 Some(a) => func(initial, a),
367 None => initial,
368 }
369 }
370
371 #[document_signature]
378 #[document_type_parameters(
382 "The lifetime of the values.",
383 "The brand of the cloneable function to use.",
384 "The type of the elements in the structure.",
385 "The type of the monoid.",
386 "The type of the mapping function."
387 )]
388 #[document_parameters("The mapping function.", "The option to fold.")]
392 fn fold_map<'a, FnBrand, A: 'a, M, 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: CloneableFn + 'a,
414 {
415 match fa {
416 Some(a) => func(a),
417 None => M::empty(),
418 }
419 }
420 }
421
422 impl Traversable for OptionBrand {
423 #[document_signature]
430 #[document_type_parameters(
434 "The lifetime of the values.",
435 "The type of the elements in the traversable structure.",
436 "The type of the elements in the resulting traversable structure.",
437 "The applicative context.",
438 "The type of the function to apply."
439 )]
440 #[document_parameters(
444 "The function to apply to each element, returning a value in an applicative context.",
445 "The option to traverse."
446 )]
447 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 match ta {
471 Some(a) => F::map(|b| Some(b), func(a)),
472 None => F::pure(None),
473 }
474 }
475 #[document_signature]
482 #[document_type_parameters(
486 "The lifetime of the values.",
487 "The type of the elements in the traversable structure.",
488 "The applicative context."
489 )]
490 #[document_parameters("The option containing the applicative value.")]
494 fn sequence<'a, A: 'a + Clone, F: Applicative>(
510 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>)>)
511 ) -> 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>)>)
512 where
513 Apply!(<F as Kind!( type Of<'a, T: 'a>: 'a; )>::Of<'a, A>): Clone,
514 Apply!(<Self as Kind!( type Of<'a, T: 'a>: 'a; )>::Of<'a, A>): Clone,
515 {
516 match ta {
517 Some(fa) => F::map(|a| Some(a), fa),
518 None => F::pure(None),
519 }
520 }
521 }
522
523 impl ParFoldable for OptionBrand {
524 #[document_signature]
531 #[document_type_parameters(
535 "The lifetime of the values.",
536 "The brand of the cloneable function wrapper.",
537 "The element type.",
538 "The monoid type."
539 )]
540 #[document_parameters("The mapping function.", "The option to fold.")]
544 fn par_fold_map<'a, FnBrand, A, M>(
560 func: <FnBrand as SendCloneableFn>::SendOf<'a, A, M>,
561 fa: Apply!(<Self as Kind!( type Of<'a, T: 'a>: 'a; )>::Of<'a, A>),
562 ) -> M
563 where
564 FnBrand: 'a + SendCloneableFn,
565 A: 'a + Clone + Send + Sync,
566 M: Monoid + Send + Sync + 'a,
567 {
568 match fa {
569 Some(a) => func(a),
570 None => M::empty(),
571 }
572 }
573 }
574
575 impl Compactable for OptionBrand {
576 #[document_signature]
583 #[document_type_parameters("The lifetime of the values.", "The type of the elements.")]
587 #[document_parameters("The nested option.")]
591 fn compact<'a, A: 'a>(
607 fa: Apply!(<Self as Kind!( type Of<'a, T: 'a>: 'a; )>::Of<
608 'a,
609 Apply!(<OptionBrand as Kind!( type Of<'a, T: 'a>: 'a; )>::Of<'a, A>),
610 >)
611 ) -> Apply!(<Self as Kind!( type Of<'a, T: 'a>: 'a; )>::Of<'a, A>) {
612 fa.flatten()
613 }
614
615 #[document_signature]
622 #[document_type_parameters(
626 "The lifetime of the values.",
627 "The type of the error value.",
628 "The type of the success value."
629 )]
630 #[document_parameters("The option of result.")]
634 fn separate<'a, E: 'a, O: 'a>(
650 fa: Apply!(<Self as Kind!( type Of<'a, T: 'a>: 'a; )>::Of<'a, Result<O, E>>)
651 ) -> (
652 Apply!(<Self as Kind!( type Of<'a, T: 'a>: 'a; )>::Of<'a, E>),
653 Apply!(<Self as Kind!( type Of<'a, T: 'a>: 'a; )>::Of<'a, O>),
654 ) {
655 match fa {
656 Some(Ok(o)) => (None, Some(o)),
657 Some(Err(e)) => (Some(e), None),
658 None => (None, None),
659 }
660 }
661 }
662
663 impl Filterable for OptionBrand {
664 #[document_signature]
671 #[document_type_parameters(
675 "The lifetime of the values.",
676 "The type of the input value.",
677 "The type of the error value.",
678 "The type of the success value.",
679 "The type of the function to apply."
680 )]
681 #[document_parameters("The function to apply.", "The option to partition.")]
685 fn partition_map<'a, A: 'a, E: 'a, O: 'a, Func>(
701 func: Func,
702 fa: Apply!(<Self as Kind!( type Of<'a, T: 'a>: 'a; )>::Of<'a, A>),
703 ) -> (
704 Apply!(<Self as Kind!( type Of<'a, T: 'a>: 'a; )>::Of<'a, E>),
705 Apply!(<Self as Kind!( type Of<'a, T: 'a>: 'a; )>::Of<'a, O>),
706 )
707 where
708 Func: Fn(A) -> Result<O, E> + 'a,
709 {
710 match fa {
711 Some(a) => match func(a) {
712 Ok(o) => (None, Some(o)),
713 Err(e) => (Some(e), None),
714 },
715 None => (None, None),
716 }
717 }
718 #[document_signature]
725 #[document_type_parameters(
729 "The lifetime of the values.",
730 "The type of the elements.",
731 "The type of the predicate."
732 )]
733 #[document_parameters("The predicate.", "The option to partition.")]
737 fn partition<'a, A: 'a + Clone, Func>(
753 func: Func,
754 fa: Apply!(<Self as Kind!( type Of<'a, T: 'a>: 'a; )>::Of<'a, A>),
755 ) -> (
756 Apply!(<Self as Kind!( type Of<'a, T: 'a>: 'a; )>::Of<'a, A>),
757 Apply!(<Self as Kind!( type Of<'a, T: 'a>: 'a; )>::Of<'a, A>),
758 )
759 where
760 Func: Fn(A) -> bool + 'a,
761 {
762 match fa {
763 Some(a) => {
764 if func(a.clone()) {
765 (None, Some(a))
766 } else {
767 (Some(a), None)
768 }
769 }
770 None => (None, None),
771 }
772 }
773
774 #[document_signature]
781 #[document_type_parameters(
785 "The lifetime of the values.",
786 "The type of the input value.",
787 "The type of the result of applying the function.",
788 "The type of the function to apply."
789 )]
790 #[document_parameters("The function to apply.", "The option to filter and map.")]
794 fn filter_map<'a, A: 'a, B: 'a, Func>(
810 func: Func,
811 fa: Apply!(<Self as Kind!( type Of<'a, T: 'a>: 'a; )>::Of<'a, A>),
812 ) -> Apply!(<Self as Kind!( type Of<'a, T: 'a>: 'a; )>::Of<'a, B>)
813 where
814 Func: Fn(A) -> Option<B> + 'a,
815 {
816 fa.and_then(func)
817 }
818
819 #[document_signature]
826 #[document_type_parameters(
830 "The lifetime of the values.",
831 "The type of the elements.",
832 "The type of the predicate."
833 )]
834 #[document_parameters("The predicate.", "The option to filter.")]
838 fn filter<'a, A: 'a + Clone, Func>(
854 func: Func,
855 fa: Apply!(<Self as Kind!( type Of<'a, T: 'a>: 'a; )>::Of<'a, A>),
856 ) -> Apply!(<Self as Kind!( type Of<'a, T: 'a>: 'a; )>::Of<'a, A>)
857 where
858 Func: Fn(A) -> bool + 'a,
859 {
860 fa.filter(|a| func(a.clone()))
861 }
862 }
863
864 impl Witherable for OptionBrand {
865 #[document_signature]
872 #[document_type_parameters(
876 "The lifetime of the values.",
877 "The applicative context.",
878 "The type of the elements in the input structure.",
879 "The type of the error values.",
880 "The type of the success values.",
881 "The type of the function to apply."
882 )]
883 #[document_parameters(
887 "The function to apply to each element, returning a `Result` in an applicative context.",
888 "The option to partition."
889 )]
890 fn wilt<'a, M: Applicative, A: 'a + Clone, E: 'a + Clone, O: 'a + Clone, Func>(
905 func: Func,
906 ta: Apply!(<Self as Kind!( type Of<'a, T: 'a>: 'a; )>::Of<'a, A>),
907 ) -> Apply!(<M as Kind!( type Of<'a, T: 'a>: 'a; )>::Of<
908 'a,
909 (
910 Apply!(<Self as Kind!( type Of<'a, T: 'a>: 'a; )>::Of<'a, E>),
911 Apply!(<Self as Kind!( type Of<'a, T: 'a>: 'a; )>::Of<'a, O>),
912 ),
913 >)
914 where
915 Func:
916 Fn(A) -> Apply!(<M as Kind!( type Of<'a, T: 'a>: 'a; )>::Of<'a, Result<O, E>>) + 'a,
917 Apply!(<Self as Kind!( type Of<'a, T: 'a>: 'a; )>::Of<'a, Result<O, E>>): Clone,
918 Apply!(<M as Kind!( type Of<'a, T: 'a>: 'a; )>::Of<'a, Result<O, E>>): Clone,
919 {
920 match ta {
921 Some(a) => M::map(
922 |res| match res {
923 Ok(o) => (None, Some(o)),
924 Err(e) => (Some(e), None),
925 },
926 func(a),
927 ),
928 None => M::pure((None, None)),
929 }
930 }
931
932 #[document_signature]
939 #[document_type_parameters(
943 "The lifetime of the values.",
944 "The applicative context.",
945 "The type of the elements in the input structure.",
946 "The type of the result of applying the function.",
947 "The type of the function to apply."
948 )]
949 #[document_parameters(
953 "The function to apply to each element, returning an `Option` in an applicative context.",
954 "The option to filter and map."
955 )]
956 fn wither<'a, M: Applicative, A: 'a + Clone, B: 'a + Clone, Func>(
971 func: Func,
972 ta: Apply!(<Self as Kind!( type Of<'a, T: 'a>: 'a; )>::Of<'a, A>),
973 ) -> Apply!(<M as Kind!( type Of<'a, T: 'a>: 'a; )>::Of<
974 'a,
975 Apply!(<Self as Kind!( type Of<'a, T: 'a>: 'a; )>::Of<'a, B>),
976 >)
977 where
978 Func: Fn(A) -> Apply!(<M as Kind!( type Of<'a, T: 'a>: 'a; )>::Of<'a, Option<B>>) + 'a,
979 Apply!(<Self as Kind!( type Of<'a, T: 'a>: 'a; )>::Of<'a, Option<B>>): Clone,
980 Apply!(<M as Kind!( type Of<'a, T: 'a>: 'a; )>::Of<'a, Option<B>>): Clone,
981 {
982 match ta {
983 Some(a) => func(a),
984 None => M::pure(None),
985 }
986 }
987 }
988}
989
990#[cfg(test)]
991mod tests {
992
993 use crate::{brands::*, classes::CloneableFn, functions::*};
994 use quickcheck_macros::quickcheck;
995
996 #[quickcheck]
1000 fn functor_identity(x: Option<i32>) -> bool {
1001 map::<OptionBrand, _, _, _>(identity, x) == x
1002 }
1003
1004 #[quickcheck]
1006 fn functor_composition(x: Option<i32>) -> bool {
1007 let f = |x: i32| x.wrapping_add(1);
1008 let g = |x: i32| x.wrapping_mul(2);
1009 map::<OptionBrand, _, _, _>(compose(f, g), x)
1010 == map::<OptionBrand, _, _, _>(f, map::<OptionBrand, _, _, _>(g, x))
1011 }
1012
1013 #[quickcheck]
1017 fn applicative_identity(v: Option<i32>) -> bool {
1018 apply::<RcFnBrand, OptionBrand, _, _>(
1019 pure::<OptionBrand, _>(<RcFnBrand as CloneableFn>::new(identity)),
1020 v,
1021 ) == v
1022 }
1023
1024 #[quickcheck]
1026 fn applicative_homomorphism(x: i32) -> bool {
1027 let f = |x: i32| x.wrapping_mul(2);
1028 apply::<RcFnBrand, OptionBrand, _, _>(
1029 pure::<OptionBrand, _>(<RcFnBrand as CloneableFn>::new(f)),
1030 pure::<OptionBrand, _>(x),
1031 ) == pure::<OptionBrand, _>(f(x))
1032 }
1033
1034 #[quickcheck]
1036 fn applicative_composition(
1037 w: Option<i32>,
1038 u_is_some: bool,
1039 v_is_some: bool,
1040 ) -> bool {
1041 let v_fn = |x: i32| x.wrapping_mul(2);
1042 let u_fn = |x: i32| x.wrapping_add(1);
1043
1044 let v = if v_is_some {
1045 pure::<OptionBrand, _>(<RcFnBrand as CloneableFn>::new(v_fn))
1046 } else {
1047 None
1048 };
1049 let u = if u_is_some {
1050 pure::<OptionBrand, _>(<RcFnBrand as CloneableFn>::new(u_fn))
1051 } else {
1052 None
1053 };
1054
1055 let vw = apply::<RcFnBrand, OptionBrand, _, _>(v.clone(), w.clone());
1057 let rhs = apply::<RcFnBrand, OptionBrand, _, _>(u.clone(), vw);
1058
1059 let uv = match (u, v) {
1062 (Some(uf), Some(vf)) => {
1063 let composed = move |x| uf(vf(x));
1064 Some(<RcFnBrand as CloneableFn>::new(composed))
1065 }
1066 _ => None,
1067 };
1068
1069 let lhs = apply::<RcFnBrand, OptionBrand, _, _>(uv, w);
1070
1071 lhs == rhs
1072 }
1073
1074 #[quickcheck]
1076 fn applicative_interchange(y: i32) -> bool {
1077 let f = |x: i32| x.wrapping_mul(2);
1079 let u = pure::<OptionBrand, _>(<RcFnBrand as CloneableFn>::new(f));
1080
1081 let lhs = apply::<RcFnBrand, OptionBrand, _, _>(u.clone(), pure::<OptionBrand, _>(y));
1082
1083 let rhs_fn =
1084 <RcFnBrand as CloneableFn>::new(move |f: std::rc::Rc<dyn Fn(i32) -> i32>| f(y));
1085 let rhs = apply::<RcFnBrand, OptionBrand, _, _>(pure::<OptionBrand, _>(rhs_fn), u);
1086
1087 lhs == rhs
1088 }
1089
1090 #[quickcheck]
1094 fn monad_left_identity(a: i32) -> bool {
1095 let f = |x: i32| Some(x.wrapping_mul(2));
1096 bind::<OptionBrand, _, _, _>(pure::<OptionBrand, _>(a), f) == f(a)
1097 }
1098
1099 #[quickcheck]
1101 fn monad_right_identity(m: Option<i32>) -> bool {
1102 bind::<OptionBrand, _, _, _>(m, pure::<OptionBrand, _>) == m
1103 }
1104
1105 #[quickcheck]
1107 fn monad_associativity(m: Option<i32>) -> bool {
1108 let f = |x: i32| Some(x.wrapping_mul(2));
1109 let g = |x: i32| Some(x.wrapping_add(1));
1110 bind::<OptionBrand, _, _, _>(bind::<OptionBrand, _, _, _>(m, f), g)
1111 == bind::<OptionBrand, _, _, _>(m, |x| bind::<OptionBrand, _, _, _>(f(x), g))
1112 }
1113
1114 #[test]
1118 fn map_none() {
1119 assert_eq!(map::<OptionBrand, _, _, _>(|x: i32| x + 1, None), None);
1120 }
1121
1122 #[test]
1124 fn bind_none() {
1125 assert_eq!(bind::<OptionBrand, _, _, _>(None, |x: i32| Some(x + 1)), None);
1126 }
1127
1128 #[test]
1130 fn bind_returning_none() {
1131 assert_eq!(bind::<OptionBrand, _, _, _>(Some(5), |_| None::<i32>), None);
1132 }
1133
1134 #[test]
1136 fn fold_right_none() {
1137 assert_eq!(
1138 crate::classes::foldable::fold_right::<RcFnBrand, OptionBrand, _, _, _>(
1139 |x: i32, acc| x + acc,
1140 0,
1141 None
1142 ),
1143 0
1144 );
1145 }
1146
1147 #[test]
1149 fn fold_left_none() {
1150 assert_eq!(
1151 crate::classes::foldable::fold_left::<RcFnBrand, OptionBrand, _, _, _>(
1152 |acc, x: i32| acc + x,
1153 0,
1154 None
1155 ),
1156 0
1157 );
1158 }
1159
1160 #[test]
1162 fn traverse_none() {
1163 assert_eq!(
1164 crate::classes::traversable::traverse::<OptionBrand, _, _, OptionBrand, _>(
1165 |x: i32| Some(x + 1),
1166 None
1167 ),
1168 Some(None)
1169 );
1170 }
1171
1172 #[test]
1174 fn traverse_returning_none() {
1175 assert_eq!(
1176 crate::classes::traversable::traverse::<OptionBrand, _, _, OptionBrand, _>(
1177 |_: i32| None::<i32>,
1178 Some(5)
1179 ),
1180 None
1181 );
1182 }
1183
1184 #[test]
1188 fn par_fold_map_none() {
1189 let x: Option<i32> = None;
1190 let f = send_cloneable_fn_new::<ArcFnBrand, _, _>(|x: i32| x.to_string());
1191 assert_eq!(par_fold_map::<ArcFnBrand, OptionBrand, _, _>(f, x), "".to_string());
1192 }
1193
1194 #[test]
1196 fn par_fold_map_some() {
1197 let x = Some(5);
1198 let f = send_cloneable_fn_new::<ArcFnBrand, _, _>(|x: i32| x.to_string());
1199 assert_eq!(par_fold_map::<ArcFnBrand, OptionBrand, _, _>(f, x), "5".to_string());
1200 }
1201
1202 #[test]
1204 fn par_fold_right_some() {
1205 let x = Some(5);
1206 let f = send_cloneable_fn_new::<ArcFnBrand, _, _>(|(a, b): (i32, i32)| a + b);
1207 assert_eq!(par_fold_right::<ArcFnBrand, OptionBrand, _, _>(f, 10, x), 15);
1208 }
1209
1210 #[quickcheck]
1214 fn filterable_filter_map_identity(x: Option<Option<i32>>) -> bool {
1215 filter_map::<OptionBrand, _, _, _>(identity, x.clone()) == compact::<OptionBrand, _>(x)
1216 }
1217
1218 #[quickcheck]
1220 fn filterable_filter_map_just(x: Option<i32>) -> bool {
1221 filter_map::<OptionBrand, _, _, _>(Some, x.clone()) == x
1222 }
1223
1224 #[quickcheck]
1226 fn filterable_filter_map_composition(x: Option<i32>) -> bool {
1227 let r = |i: i32| if i % 2 == 0 { Some(i) } else { None };
1228 let l = |i: i32| if i > 5 { Some(i) } else { None };
1229 let composed = |i| r(i).and_then(l);
1230
1231 filter_map::<OptionBrand, _, _, _>(composed, x.clone())
1232 == filter_map::<OptionBrand, _, _, _>(l, filter_map::<OptionBrand, _, _, _>(r, x))
1233 }
1234
1235 #[quickcheck]
1237 fn filterable_filter_consistency(x: Option<i32>) -> bool {
1238 let p = |i: i32| i % 2 == 0;
1239 let maybe_bool = |i| if p(i) { Some(i) } else { None };
1240
1241 filter::<OptionBrand, _, _>(p, x.clone())
1242 == filter_map::<OptionBrand, _, _, _>(maybe_bool, x)
1243 }
1244
1245 #[quickcheck]
1247 fn filterable_partition_map_identity(x: Option<Result<i32, i32>>) -> bool {
1248 partition_map::<OptionBrand, _, _, _, _>(identity, x.clone())
1249 == separate::<OptionBrand, _, _>(x)
1250 }
1251
1252 #[quickcheck]
1254 fn filterable_partition_map_right_identity(x: Option<i32>) -> bool {
1255 let (_, oks) = partition_map::<OptionBrand, _, _, _, _>(Ok::<_, i32>, x.clone());
1256 oks == x
1257 }
1258
1259 #[quickcheck]
1261 fn filterable_partition_map_left_identity(x: Option<i32>) -> bool {
1262 let (errs, _) = partition_map::<OptionBrand, _, _, _, _>(Err::<i32, _>, x.clone());
1263 errs == x
1264 }
1265
1266 #[quickcheck]
1268 fn filterable_partition_consistency(x: Option<i32>) -> bool {
1269 let p = |i: i32| i % 2 == 0;
1270 let either_bool = |i| if p(i) { Ok(i) } else { Err(i) };
1271
1272 let (not_satisfied, satisfied) = partition::<OptionBrand, _, _>(p, x.clone());
1273 let (errs, oks) = partition_map::<OptionBrand, _, _, _, _>(either_bool, x);
1274
1275 satisfied == oks && not_satisfied == errs
1276 }
1277
1278 #[quickcheck]
1282 fn witherable_identity(x: Option<i32>) -> bool {
1283 wither::<OptionBrand, OptionBrand, _, _, _>(|i| Some(Some(i)), x.clone()) == Some(x)
1284 }
1285
1286 #[quickcheck]
1288 fn witherable_wilt_consistency(x: Option<i32>) -> bool {
1289 let p = |i: i32| Some(if i % 2 == 0 { Ok(i) } else { Err(i) });
1290
1291 let lhs = wilt::<OptionBrand, OptionBrand, _, _, _, _>(p, x.clone());
1292 let rhs = map::<OptionBrand, _, _, _>(
1293 |res| separate::<OptionBrand, _, _>(res),
1294 traverse::<OptionBrand, _, _, OptionBrand, _>(p, x),
1295 );
1296
1297 lhs == rhs
1298 }
1299
1300 #[quickcheck]
1302 fn witherable_wither_consistency(x: Option<i32>) -> bool {
1303 let p = |i: i32| Some(if i % 2 == 0 { Some(i) } else { None });
1304
1305 let lhs = wither::<OptionBrand, OptionBrand, _, _, _>(p, x.clone());
1306 let rhs = map::<OptionBrand, _, _, _>(
1307 |opt| compact::<OptionBrand, _>(opt),
1308 traverse::<OptionBrand, _, _, OptionBrand, _>(p, x),
1309 );
1310
1311 lhs == rhs
1312 }
1313
1314 #[test]
1318 fn compact_some_none() {
1319 assert_eq!(compact::<OptionBrand, _>(Some(None::<i32>)), None);
1320 }
1321
1322 #[test]
1324 fn compact_some_some() {
1325 assert_eq!(compact::<OptionBrand, _>(Some(Some(5))), Some(5));
1326 }
1327
1328 #[test]
1330 fn compact_none() {
1331 assert_eq!(compact::<OptionBrand, _>(None::<Option<i32>>), None);
1332 }
1333
1334 #[test]
1336 fn separate_some_ok() {
1337 let (errs, oks) = separate::<OptionBrand, _, _>(Some(Ok::<i32, &str>(5)));
1338 assert_eq!(oks, Some(5));
1339 assert_eq!(errs, None);
1340 }
1341
1342 #[test]
1344 fn separate_some_err() {
1345 let (errs, oks) = separate::<OptionBrand, _, _>(Some(Err::<i32, &str>("error")));
1346 assert_eq!(oks, None);
1347 assert_eq!(errs, Some("error"));
1348 }
1349
1350 #[test]
1352 fn separate_none() {
1353 let (errs, oks) = separate::<OptionBrand, _, _>(None::<Result<i32, &str>>);
1354 assert_eq!(oks, None);
1355 assert_eq!(errs, None);
1356 }
1357
1358 #[test]
1360 fn partition_map_none() {
1361 let (errs, oks) =
1362 partition_map::<OptionBrand, _, _, _, _>(|x: i32| Ok::<i32, i32>(x), None::<i32>);
1363 assert_eq!(oks, None);
1364 assert_eq!(errs, None);
1365 }
1366
1367 #[test]
1369 fn partition_none() {
1370 let (not_satisfied, satisfied) =
1371 partition::<OptionBrand, _, _>(|x: i32| x > 0, None::<i32>);
1372 assert_eq!(satisfied, None);
1373 assert_eq!(not_satisfied, None);
1374 }
1375
1376 #[test]
1378 fn filter_map_none() {
1379 assert_eq!(filter_map::<OptionBrand, _, _, _>(|x: i32| Some(x), None::<i32>), None);
1380 }
1381
1382 #[test]
1384 fn filter_none() {
1385 assert_eq!(filter::<OptionBrand, _, _>(|x: i32| x > 0, None::<i32>), None);
1386 }
1387
1388 #[test]
1390 fn wilt_none() {
1391 let res = wilt::<OptionBrand, OptionBrand, _, _, _, _>(
1392 |x: i32| Some(Ok::<i32, i32>(x)),
1393 None::<i32>,
1394 );
1395 assert_eq!(res, Some((None, None)));
1396 }
1397
1398 #[test]
1400 fn wither_none() {
1401 let res = wither::<OptionBrand, OptionBrand, _, _, _>(|x: i32| Some(Some(x)), None::<i32>);
1402 assert_eq!(res, Some(None));
1403 }
1404}