1#[fp_macros::document_module]
6mod inner {
7 use {
8 crate::{
9 Apply,
10 brands::OptionBrand,
11 classes::{
12 Alt,
13 Applicative,
14 ApplyFirst,
15 ApplySecond,
16 CloneableFn,
17 Compactable,
18 Filterable,
19 Foldable,
20 Functor,
21 Lift,
22 MonadRec,
23 Monoid,
24 Plus,
25 Pointed,
26 Semiapplicative,
27 Semimonad,
28 Traversable,
29 Witherable,
30 foldable_with_index::FoldableWithIndex,
31 functor_with_index::FunctorWithIndex,
32 traversable_with_index::TraversableWithIndex,
33 with_index::WithIndex,
34 },
35 impl_kind,
36 kinds::*,
37 },
38 core::ops::ControlFlow,
39 fp_macros::*,
40 };
41
42 impl_kind! {
43 for OptionBrand {
44 type Of<'a, A: 'a>: 'a = Option<A>;
45 }
46 }
47
48 impl Functor for OptionBrand {
49 #[document_signature]
53 #[document_type_parameters(
55 "The lifetime of the value.",
56 "The type of the value inside the option.",
57 "The type of the result of applying the function."
58 )]
59 #[document_parameters("The function to apply to the value.", "The option to map over.")]
61 #[document_returns(
63 "A new option containing the result of applying the function, or `None`."
64 )]
65 #[document_examples]
67 fn map<'a, A: 'a, B: 'a>(
79 func: impl Fn(A) -> B + 'a,
80 fa: Apply!(<Self as Kind!( type Of<'a, T: 'a>: 'a; )>::Of<'a, A>),
81 ) -> Apply!(<Self as Kind!( type Of<'a, T: 'a>: 'a; )>::Of<'a, B>) {
82 fa.map(func)
83 }
84 }
85
86 impl Lift for OptionBrand {
87 #[document_signature]
91 #[document_type_parameters(
93 "The lifetime of the values.",
94 "The type of the first option's value.",
95 "The type of the second option's value.",
96 "The return type of the function."
97 )]
98 #[document_parameters(
100 "The binary function to apply.",
101 "The first option.",
102 "The second option."
103 )]
104 #[document_returns("`Some(f(a, b))` if both options are `Some`, otherwise `None`.")]
106 #[document_examples]
107 fn lift2<'a, A, B, C>(
120 func: impl Fn(A, B) -> C + 'a,
121 fa: Apply!(<Self as Kind!( type Of<'a, T: 'a>: 'a; )>::Of<'a, A>),
122 fb: Apply!(<Self as Kind!( type Of<'a, T: 'a>: 'a; )>::Of<'a, B>),
123 ) -> Apply!(<Self as Kind!( type Of<'a, T: 'a>: 'a; )>::Of<'a, C>)
124 where
125 A: 'a,
126 B: 'a,
127 C: 'a, {
128 fa.zip(fb).map(|(a, b)| func(a, b))
129 }
130 }
131
132 impl Pointed for OptionBrand {
133 #[document_signature]
137 #[document_type_parameters("The lifetime of the value.", "The type of the value to wrap.")]
139 #[document_parameters("The value to wrap.")]
141 #[document_returns("`Some(a)`.")]
143 #[document_examples]
145 fn pure<'a, A: 'a>(a: A) -> Apply!(<Self as Kind!( type Of<'a, T: 'a>: 'a; )>::Of<'a, A>) {
156 Some(a)
157 }
158 }
159
160 impl ApplyFirst for OptionBrand {}
161 impl ApplySecond for OptionBrand {}
162
163 impl Semiapplicative for OptionBrand {
164 #[document_signature]
168 #[document_type_parameters(
170 "The lifetime of the values.",
171 "The brand of the cloneable function wrapper.",
172 "The type of the input value.",
173 "The type of the output value."
174 )]
175 #[document_parameters(
177 "The option containing the function.",
178 "The option containing the value."
179 )]
180 #[document_returns("`Some(f(a))` if both are `Some`, otherwise `None`.")]
182 #[document_examples]
183 fn apply<'a, FnBrand: 'a + CloneableFn, A: 'a + Clone, B: 'a>(
197 ff: Apply!(<Self as Kind!( type Of<'a, T: 'a>: 'a; )>::Of<'a, <FnBrand as CloneableFn>::Of<'a, A, B>>),
198 fa: Apply!(<Self as Kind!( type Of<'a, T: 'a>: 'a; )>::Of<'a, A>),
199 ) -> Apply!(<Self as Kind!( type Of<'a, T: 'a>: 'a; )>::Of<'a, B>) {
200 match (ff, fa) {
201 (Some(f), Some(a)) => Some(f(a)),
202 _ => None,
203 }
204 }
205 }
206
207 impl Semimonad for OptionBrand {
208 #[document_signature]
212 #[document_type_parameters(
214 "The lifetime of the values.",
215 "The type of the result of the first computation.",
216 "The type of the result of the second computation."
217 )]
218 #[document_parameters(
220 "The first option.",
221 "The function to apply to the value inside the option."
222 )]
223 #[document_returns(
225 "The result of applying `f` to the value if `ma` is `Some`, otherwise `None`."
226 )]
227 #[document_examples]
228 fn bind<'a, A: 'a, B: 'a>(
240 ma: Apply!(<Self as Kind!( type Of<'a, T: 'a>: 'a; )>::Of<'a, A>),
241 func: impl Fn(A) -> Apply!(<Self as Kind!( type Of<'a, T: 'a>: 'a; )>::Of<'a, B>) + 'a,
242 ) -> Apply!(<Self as Kind!( type Of<'a, T: 'a>: 'a; )>::Of<'a, B>) {
243 ma.and_then(func)
244 }
245 }
246
247 impl Alt for OptionBrand {
248 #[document_signature]
252 #[document_type_parameters("The lifetime of the values.", "The type of the value.")]
254 #[document_parameters("The first option.", "The second option.")]
256 #[document_returns("The first `Some` value, or `None`.")]
258 #[document_examples]
259 fn alt<'a, A: 'a>(
272 fa1: Apply!(<Self as Kind!( type Of<'a, T: 'a>: 'a; )>::Of<'a, A>),
273 fa2: Apply!(<Self as Kind!( type Of<'a, T: 'a>: 'a; )>::Of<'a, A>),
274 ) -> Apply!(<Self as Kind!( type Of<'a, T: 'a>: 'a; )>::Of<'a, A>) {
275 fa1.or(fa2)
276 }
277 }
278
279 impl Plus for OptionBrand {
280 #[document_signature]
282 #[document_type_parameters("The lifetime of the value.", "The type of the value.")]
284 #[document_returns("`None`.")]
286 #[document_examples]
287 fn empty<'a, A: 'a>() -> Apply!(<Self as Kind!( type Of<'a, T: 'a>: 'a; )>::Of<'a, A>) {
298 None
299 }
300 }
301
302 impl Foldable for OptionBrand {
303 #[document_signature]
307 #[document_type_parameters(
309 "The lifetime of the values.",
310 "The brand of the cloneable function to use.",
311 "The type of the elements in the structure.",
312 "The type of the accumulator."
313 )]
314 #[document_parameters("The folding function.", "The initial value.", "The option to fold.")]
316 #[document_returns("`func(a, initial)` if `fa` is `Some(a)`, otherwise `initial`.")]
318 #[document_examples]
320 fn fold_right<'a, FnBrand, A: 'a + Clone, B: 'a>(
332 func: impl Fn(A, B) -> B + 'a,
333 initial: B,
334 fa: Apply!(<Self as Kind!( type Of<'a, T: 'a>: 'a; )>::Of<'a, A>),
335 ) -> B
336 where
337 FnBrand: CloneableFn + 'a, {
338 match fa {
339 Some(a) => func(a, initial),
340 None => initial,
341 }
342 }
343
344 #[document_signature]
348 #[document_type_parameters(
350 "The lifetime of the values.",
351 "The brand of the cloneable function to use.",
352 "The type of the elements in the structure.",
353 "The type of the accumulator."
354 )]
355 #[document_parameters(
357 "The function to apply to the accumulator and each element.",
358 "The initial value of the accumulator.",
359 "The option to fold."
360 )]
361 #[document_returns("`f(initial, a)` if `fa` is `Some(a)`, otherwise `initial`.")]
363 #[document_examples]
364 fn fold_left<'a, FnBrand, A: 'a + Clone, B: 'a>(
376 func: impl Fn(B, A) -> B + 'a,
377 initial: B,
378 fa: Apply!(<Self as Kind!( type Of<'a, T: 'a>: 'a; )>::Of<'a, A>),
379 ) -> B
380 where
381 FnBrand: CloneableFn + 'a, {
382 match fa {
383 Some(a) => func(initial, a),
384 None => initial,
385 }
386 }
387
388 #[document_signature]
392 #[document_type_parameters(
394 "The lifetime of the values.",
395 "The brand of the cloneable function to use.",
396 "The type of the elements in the structure.",
397 "The type of the monoid."
398 )]
399 #[document_parameters("The mapping function.", "The option to fold.")]
401 #[document_returns("`func(a)` if `fa` is `Some(a)`, otherwise `M::empty()`.")]
403 #[document_examples]
405 fn fold_map<'a, FnBrand, A: 'a + Clone, M>(
417 func: impl Fn(A) -> M + 'a,
418 fa: Apply!(<Self as Kind!( type Of<'a, T: 'a>: 'a; )>::Of<'a, A>),
419 ) -> M
420 where
421 M: Monoid + 'a,
422 FnBrand: CloneableFn + 'a, {
423 match fa {
424 Some(a) => func(a),
425 None => M::empty(),
426 }
427 }
428 }
429
430 impl Traversable for OptionBrand {
431 #[document_signature]
435 #[document_type_parameters(
437 "The lifetime of the values.",
438 "The type of the elements in the traversable structure.",
439 "The type of the elements in the resulting traversable structure.",
440 "The applicative context."
441 )]
442 #[document_parameters(
444 "The function to apply to each element, returning a value in an applicative context.",
445 "The option to traverse."
446 )]
447 #[document_returns("The option wrapped in the applicative context.")]
449 #[document_examples]
450 fn traverse<'a, A: 'a + Clone, B: 'a + Clone, F: Applicative>(
462 func: impl Fn(A) -> Apply!(<F as Kind!( type Of<'a, T: 'a>: 'a; )>::Of<'a, B>) + 'a,
463 ta: Apply!(<Self as Kind!( type Of<'a, T: 'a>: 'a; )>::Of<'a, A>),
464 ) -> 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>)>)
465 where
466 Apply!(<Self as Kind!( type Of<'a, T: 'a>: 'a; )>::Of<'a, B>): Clone, {
467 match ta {
468 Some(a) => F::map(|b| Some(b), func(a)),
469 None => F::pure(None),
470 }
471 }
472
473 #[document_signature]
477 #[document_type_parameters(
479 "The lifetime of the values.",
480 "The type of the elements in the traversable structure.",
481 "The applicative context."
482 )]
483 #[document_parameters("The option containing the applicative value.")]
485 #[document_returns("The result of the traversal.")]
487 #[document_examples]
492 fn sequence<'a, A: 'a + Clone, F: Applicative>(
504 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>)>)
505 ) -> 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>)>)
506 where
507 Apply!(<F as Kind!( type Of<'a, T: 'a>: 'a; )>::Of<'a, A>): Clone,
508 Apply!(<Self as Kind!( type Of<'a, T: 'a>: 'a; )>::Of<'a, A>): Clone, {
509 match ta {
510 Some(fa) => F::map(|a| Some(a), fa),
511 None => F::pure(None),
512 }
513 }
514 }
515
516 impl WithIndex for OptionBrand {
517 type Index = ();
518 }
519
520 impl FunctorWithIndex for OptionBrand {
521 #[document_signature]
523 #[document_type_parameters(
524 "The lifetime of the value.",
525 "The type of the value inside the option.",
526 "The type of the result of applying the function."
527 )]
528 #[document_parameters(
529 "The function to apply to the value and its index.",
530 "The option to map over."
531 )]
532 #[document_returns(
533 "A new option containing the result of applying the function, or `None`."
534 )]
535 #[document_examples]
536 fn map_with_index<'a, A: 'a, B: 'a>(
548 f: impl Fn((), A) -> B + 'a,
549 fa: Option<A>,
550 ) -> Option<B> {
551 fa.map(|a| f((), a))
552 }
553 }
554
555 impl FoldableWithIndex for OptionBrand {
556 #[document_signature]
558 #[document_type_parameters(
559 "The lifetime of the value.",
560 "The type of the value inside the option.",
561 "The monoid type."
562 )]
563 #[document_parameters(
564 "The function to apply to the value and its index.",
565 "The option to fold."
566 )]
567 #[document_returns("The monoid value.")]
568 #[document_examples]
569 fn fold_map_with_index<'a, A: 'a + Clone, R: Monoid>(
581 f: impl Fn((), A) -> R + 'a,
582 fa: Option<A>,
583 ) -> R {
584 match fa {
585 Some(a) => f((), a),
586 None => R::empty(),
587 }
588 }
589 }
590
591 impl TraversableWithIndex for OptionBrand {
592 #[document_signature]
594 #[document_type_parameters(
595 "The lifetime of the value.",
596 "The type of the value inside the option.",
597 "The type of the result.",
598 "The applicative context."
599 )]
600 #[document_parameters(
601 "The function to apply to the value and its index, returning a value in an applicative context.",
602 "The option to traverse."
603 )]
604 #[document_returns("The option wrapped in the applicative context.")]
605 #[document_examples]
606 fn traverse_with_index<'a, A: 'a, B: 'a + Clone, M: Applicative>(
621 f: impl Fn((), A) -> M::Of<'a, B> + 'a,
622 ta: Option<A>,
623 ) -> M::Of<'a, Option<B>> {
624 match ta {
625 Some(a) => M::map(|b| Some(b), f((), a)),
626 None => M::pure(None),
627 }
628 }
629 }
630
631 impl Compactable for OptionBrand {
632 #[document_signature]
636 #[document_type_parameters("The lifetime of the values.", "The type of the elements.")]
638 #[document_parameters("The nested option.")]
640 #[document_returns("The flattened option.")]
642 #[document_examples]
644 fn compact<'a, A: 'a>(
656 fa: Apply!(<Self as Kind!( type Of<'a, T: 'a>: 'a; )>::Of<
657 'a,
658 Apply!(<OptionBrand as Kind!( type Of<'a, T: 'a>: 'a; )>::Of<'a, A>),
659 >)
660 ) -> Apply!(<Self as Kind!( type Of<'a, T: 'a>: 'a; )>::Of<'a, A>) {
661 fa.flatten()
662 }
663
664 #[document_signature]
668 #[document_type_parameters(
670 "The lifetime of the values.",
671 "The type of the error value.",
672 "The type of the success value."
673 )]
674 #[document_parameters("The option of result.")]
676 #[document_returns("A pair of options.")]
678 #[document_examples]
680 fn separate<'a, E: 'a, O: 'a>(
693 fa: Apply!(<Self as Kind!( type Of<'a, T: 'a>: 'a; )>::Of<'a, Result<O, E>>)
694 ) -> (
695 Apply!(<Self as Kind!( type Of<'a, T: 'a>: 'a; )>::Of<'a, E>),
696 Apply!(<Self as Kind!( type Of<'a, T: 'a>: 'a; )>::Of<'a, O>),
697 ) {
698 match fa {
699 Some(Ok(o)) => (None, Some(o)),
700 Some(Err(e)) => (Some(e), None),
701 None => (None, None),
702 }
703 }
704 }
705
706 impl Filterable for OptionBrand {
707 #[document_signature]
711 #[document_type_parameters(
713 "The lifetime of the values.",
714 "The type of the input value.",
715 "The type of the error value.",
716 "The type of the success value."
717 )]
718 #[document_parameters("The function to apply.", "The option to partition.")]
720 #[document_returns("A pair of options.")]
722 #[document_examples]
724 fn partition_map<'a, A: 'a, E: 'a, O: 'a>(
738 func: impl Fn(A) -> Result<O, E> + 'a,
739 fa: Apply!(<Self as Kind!( type Of<'a, T: 'a>: 'a; )>::Of<'a, A>),
740 ) -> (
741 Apply!(<Self as Kind!( type Of<'a, T: 'a>: 'a; )>::Of<'a, E>),
742 Apply!(<Self as Kind!( type Of<'a, T: 'a>: 'a; )>::Of<'a, O>),
743 ) {
744 match fa {
745 Some(a) => match func(a) {
746 Ok(o) => (None, Some(o)),
747 Err(e) => (Some(e), None),
748 },
749 None => (None, None),
750 }
751 }
752
753 #[document_signature]
757 #[document_type_parameters("The lifetime of the values.", "The type of the elements.")]
759 #[document_parameters("The predicate.", "The option to partition.")]
761 #[document_returns("A pair of options.")]
763 #[document_examples]
765 fn partition<'a, A: 'a + Clone>(
778 func: impl Fn(A) -> bool + 'a,
779 fa: Apply!(<Self as Kind!( type Of<'a, T: 'a>: 'a; )>::Of<'a, A>),
780 ) -> (
781 Apply!(<Self as Kind!( type Of<'a, T: 'a>: 'a; )>::Of<'a, A>),
782 Apply!(<Self as Kind!( type Of<'a, T: 'a>: 'a; )>::Of<'a, A>),
783 ) {
784 match fa {
785 Some(a) =>
786 if func(a.clone()) {
787 (None, Some(a))
788 } else {
789 (Some(a), None)
790 },
791 None => (None, None),
792 }
793 }
794
795 #[document_signature]
799 #[document_type_parameters(
801 "The lifetime of the values.",
802 "The type of the input value.",
803 "The type of the result of applying the function."
804 )]
805 #[document_parameters("The function to apply.", "The option to filter and map.")]
807 #[document_returns("The filtered and mapped option.")]
809 #[document_examples]
811 fn filter_map<'a, A: 'a, B: 'a>(
823 func: impl Fn(A) -> Option<B> + 'a,
824 fa: Apply!(<Self as Kind!( type Of<'a, T: 'a>: 'a; )>::Of<'a, A>),
825 ) -> Apply!(<Self as Kind!( type Of<'a, T: 'a>: 'a; )>::Of<'a, B>) {
826 fa.and_then(func)
827 }
828
829 #[document_signature]
833 #[document_type_parameters("The lifetime of the values.", "The type of the elements.")]
835 #[document_parameters("The predicate.", "The option to filter.")]
837 #[document_returns("The filtered option.")]
839 #[document_examples]
841 fn filter<'a, A: 'a + Clone>(
853 func: impl Fn(A) -> bool + 'a,
854 fa: Apply!(<Self as Kind!( type Of<'a, T: 'a>: 'a; )>::Of<'a, A>),
855 ) -> Apply!(<Self as Kind!( type Of<'a, T: 'a>: 'a; )>::Of<'a, A>) {
856 fa.filter(|a| func(a.clone()))
857 }
858 }
859
860 impl Witherable for OptionBrand {
861 #[document_signature]
865 #[document_type_parameters(
867 "The lifetime of the values.",
868 "The applicative context.",
869 "The type of the elements in the input structure.",
870 "The type of the error values.",
871 "The type of the success values."
872 )]
873 #[document_parameters(
875 "The function to apply to each element, returning a `Result` in an applicative context.",
876 "The option to partition."
877 )]
878 #[document_returns("The partitioned option wrapped in the applicative context.")]
880 #[document_examples]
881 fn wilt<'a, M: Applicative, A: 'a + Clone, E: 'a + Clone, O: 'a + Clone>(
894 func: impl Fn(A) -> Apply!(<M as Kind!( type Of<'a, T: 'a>: 'a; )>::Of<'a, Result<O, E>>)
895 + 'a,
896 ta: Apply!(<Self as Kind!( type Of<'a, T: 'a>: 'a; )>::Of<'a, A>),
897 ) -> Apply!(<M as Kind!( type Of<'a, T: 'a>: 'a; )>::Of<
898 'a,
899 (
900 Apply!(<Self as Kind!( type Of<'a, T: 'a>: 'a; )>::Of<'a, E>),
901 Apply!(<Self as Kind!( type Of<'a, T: 'a>: 'a; )>::Of<'a, O>),
902 ),
903 >)
904 where
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 match ta {
908 Some(a) => M::map(
909 |res| match res {
910 Ok(o) => (None, Some(o)),
911 Err(e) => (Some(e), None),
912 },
913 func(a),
914 ),
915 None => M::pure((None, None)),
916 }
917 }
918
919 #[document_signature]
923 #[document_type_parameters(
925 "The lifetime of the values.",
926 "The applicative context.",
927 "The type of the elements in the input structure.",
928 "The type of the result of applying the function."
929 )]
930 #[document_parameters(
932 "The function to apply to each element, returning an `Option` in an applicative context.",
933 "The option to filter and map."
934 )]
935 #[document_returns("The filtered and mapped option wrapped in the applicative context.")]
937 #[document_examples]
938 fn wither<'a, M: Applicative, A: 'a + Clone, B: 'a + Clone>(
953 func: impl Fn(A) -> Apply!(<M as Kind!( type Of<'a, T: 'a>: 'a; )>::Of<'a, Option<B>>) + 'a,
954 ta: Apply!(<Self as Kind!( type Of<'a, T: 'a>: 'a; )>::Of<'a, A>),
955 ) -> Apply!(<M as Kind!( type Of<'a, T: 'a>: 'a; )>::Of<
956 'a,
957 Apply!(<Self as Kind!( type Of<'a, T: 'a>: 'a; )>::Of<'a, B>),
958 >)
959 where
960 Apply!(<Self as Kind!( type Of<'a, T: 'a>: 'a; )>::Of<'a, Option<B>>): Clone,
961 Apply!(<M as Kind!( type Of<'a, T: 'a>: 'a; )>::Of<'a, Option<B>>): Clone, {
962 match ta {
963 Some(a) => func(a),
964 None => M::pure(None),
965 }
966 }
967 }
968
969 impl MonadRec for OptionBrand {
970 #[document_signature]
977 #[document_type_parameters(
979 "The lifetime of the computation.",
980 "The type of the initial value and loop state.",
981 "The type of the result."
982 )]
983 #[document_parameters("The step function.", "The initial value.")]
985 #[document_returns(
987 "The result of the computation, or `None` if the step function returned `None`."
988 )]
989 #[document_examples]
991 fn tail_rec_m<'a, A: 'a, B: 'a>(
1011 func: impl Fn(
1012 A,
1013 )
1014 -> Apply!(<Self as Kind!( type Of<'a, T: 'a>: 'a; )>::Of<'a, ControlFlow<B, A>>)
1015 + 'a,
1016 initial: A,
1017 ) -> Apply!(<Self as Kind!( type Of<'a, T: 'a>: 'a; )>::Of<'a, B>) {
1018 let mut current = initial;
1019 loop {
1020 match func(current) {
1021 None => return None,
1022 Some(ControlFlow::Continue(next)) => current = next,
1023 Some(ControlFlow::Break(b)) => return Some(b),
1024 }
1025 }
1026 }
1027 }
1028}
1029
1030#[cfg(test)]
1031mod tests {
1032
1033 use {
1034 crate::{
1035 brands::*,
1036 classes::CloneableFn,
1037 functions::*,
1038 },
1039 quickcheck_macros::quickcheck,
1040 };
1041
1042 #[quickcheck]
1046 fn functor_identity(x: Option<i32>) -> bool {
1047 map::<OptionBrand, _, _>(identity, x) == x
1048 }
1049
1050 #[quickcheck]
1052 fn functor_composition(x: Option<i32>) -> bool {
1053 let f = |x: i32| x.wrapping_add(1);
1054 let g = |x: i32| x.wrapping_mul(2);
1055 map::<OptionBrand, _, _>(compose(f, g), x)
1056 == map::<OptionBrand, _, _>(f, map::<OptionBrand, _, _>(g, x))
1057 }
1058
1059 #[quickcheck]
1063 fn applicative_identity(v: Option<i32>) -> bool {
1064 apply::<RcFnBrand, OptionBrand, _, _>(
1065 pure::<OptionBrand, _>(<RcFnBrand as CloneableFn>::new(identity)),
1066 v,
1067 ) == v
1068 }
1069
1070 #[quickcheck]
1072 fn applicative_homomorphism(x: i32) -> bool {
1073 let f = |x: i32| x.wrapping_mul(2);
1074 apply::<RcFnBrand, OptionBrand, _, _>(
1075 pure::<OptionBrand, _>(<RcFnBrand as CloneableFn>::new(f)),
1076 pure::<OptionBrand, _>(x),
1077 ) == pure::<OptionBrand, _>(f(x))
1078 }
1079
1080 #[quickcheck]
1082 fn applicative_composition(
1083 w: Option<i32>,
1084 u_is_some: bool,
1085 v_is_some: bool,
1086 ) -> bool {
1087 let v_fn = |x: i32| x.wrapping_mul(2);
1088 let u_fn = |x: i32| x.wrapping_add(1);
1089
1090 let v = if v_is_some {
1091 pure::<OptionBrand, _>(<RcFnBrand as CloneableFn>::new(v_fn))
1092 } else {
1093 None
1094 };
1095 let u = if u_is_some {
1096 pure::<OptionBrand, _>(<RcFnBrand as CloneableFn>::new(u_fn))
1097 } else {
1098 None
1099 };
1100
1101 let vw = apply::<RcFnBrand, OptionBrand, _, _>(v.clone(), w);
1103 let rhs = apply::<RcFnBrand, OptionBrand, _, _>(u.clone(), vw);
1104
1105 let uv = match (u, v) {
1108 (Some(uf), Some(vf)) => {
1109 let composed = move |x| uf(vf(x));
1110 Some(<RcFnBrand as CloneableFn>::new(composed))
1111 }
1112 _ => None,
1113 };
1114
1115 let lhs = apply::<RcFnBrand, OptionBrand, _, _>(uv, w);
1116
1117 lhs == rhs
1118 }
1119
1120 #[quickcheck]
1122 fn applicative_interchange(y: i32) -> bool {
1123 let f = |x: i32| x.wrapping_mul(2);
1125 let u = pure::<OptionBrand, _>(<RcFnBrand as CloneableFn>::new(f));
1126
1127 let lhs = apply::<RcFnBrand, OptionBrand, _, _>(u.clone(), pure::<OptionBrand, _>(y));
1128
1129 let rhs_fn =
1130 <RcFnBrand as CloneableFn>::new(move |f: std::rc::Rc<dyn Fn(i32) -> i32>| f(y));
1131 let rhs = apply::<RcFnBrand, OptionBrand, _, _>(pure::<OptionBrand, _>(rhs_fn), u);
1132
1133 lhs == rhs
1134 }
1135
1136 #[quickcheck]
1140 fn monad_left_identity(a: i32) -> bool {
1141 let f = |x: i32| Some(x.wrapping_mul(2));
1142 bind::<OptionBrand, _, _>(pure::<OptionBrand, _>(a), f) == f(a)
1143 }
1144
1145 #[quickcheck]
1147 fn monad_right_identity(m: Option<i32>) -> bool {
1148 bind::<OptionBrand, _, _>(m, pure::<OptionBrand, _>) == m
1149 }
1150
1151 #[quickcheck]
1153 fn monad_associativity(m: Option<i32>) -> bool {
1154 let f = |x: i32| Some(x.wrapping_mul(2));
1155 let g = |x: i32| Some(x.wrapping_add(1));
1156 bind::<OptionBrand, _, _>(bind::<OptionBrand, _, _>(m, f), g)
1157 == bind::<OptionBrand, _, _>(m, |x| bind::<OptionBrand, _, _>(f(x), g))
1158 }
1159
1160 #[test]
1164 fn map_none() {
1165 assert_eq!(map::<OptionBrand, _, _>(|x: i32| x + 1, None), None);
1166 }
1167
1168 #[test]
1170 fn bind_none() {
1171 assert_eq!(bind::<OptionBrand, _, _>(None, |x: i32| Some(x + 1)), None);
1172 }
1173
1174 #[test]
1176 fn bind_returning_none() {
1177 assert_eq!(bind::<OptionBrand, _, _>(Some(5), |_| None::<i32>), None);
1178 }
1179
1180 #[test]
1182 fn fold_right_none() {
1183 assert_eq!(
1184 crate::classes::foldable::fold_right::<RcFnBrand, OptionBrand, _, _>(
1185 |x: i32, acc| x + acc,
1186 0,
1187 None
1188 ),
1189 0
1190 );
1191 }
1192
1193 #[test]
1195 fn fold_left_none() {
1196 assert_eq!(
1197 crate::classes::foldable::fold_left::<RcFnBrand, OptionBrand, _, _>(
1198 |acc, x: i32| acc + x,
1199 0,
1200 None
1201 ),
1202 0
1203 );
1204 }
1205
1206 #[test]
1208 fn traverse_none() {
1209 assert_eq!(
1210 crate::classes::traversable::traverse::<OptionBrand, _, _, OptionBrand>(
1211 |x: i32| Some(x + 1),
1212 None
1213 ),
1214 Some(None)
1215 );
1216 }
1217
1218 #[test]
1220 fn traverse_returning_none() {
1221 assert_eq!(
1222 crate::classes::traversable::traverse::<OptionBrand, _, _, OptionBrand>(
1223 |_: i32| None::<i32>,
1224 Some(5)
1225 ),
1226 None
1227 );
1228 }
1229
1230 #[quickcheck]
1234 fn monad_rec_identity(x: i32) -> bool {
1235 use {
1236 crate::classes::monad_rec::tail_rec_m,
1237 core::ops::ControlFlow,
1238 };
1239 tail_rec_m::<OptionBrand, _, _>(|a| Some(ControlFlow::Break(a)), x) == Some(x)
1240 }
1241
1242 #[test]
1244 fn monad_rec_sum_range() {
1245 use {
1246 crate::classes::monad_rec::tail_rec_m,
1247 core::ops::ControlFlow,
1248 };
1249 let result = tail_rec_m::<OptionBrand, _, _>(
1251 |(n, acc)| {
1252 if n == 0 {
1253 Some(ControlFlow::Break(acc))
1254 } else {
1255 Some(ControlFlow::Continue((n - 1, acc + n)))
1256 }
1257 },
1258 (100i64, 0i64),
1259 );
1260 assert_eq!(result, Some(5050));
1261 }
1262
1263 #[test]
1265 fn monad_rec_short_circuit() {
1266 use {
1267 crate::classes::monad_rec::tail_rec_m,
1268 core::ops::ControlFlow,
1269 };
1270 let result: Option<i32> = tail_rec_m::<OptionBrand, _, _>(
1271 |n| {
1272 if n == 5 { None } else { Some(ControlFlow::Continue(n + 1)) }
1273 },
1274 0,
1275 );
1276 assert_eq!(result, None);
1277 }
1278
1279 #[test]
1281 fn monad_rec_stack_safety() {
1282 use {
1283 crate::classes::monad_rec::tail_rec_m,
1284 core::ops::ControlFlow,
1285 };
1286 let iterations: i64 = 200_000;
1287 let result = tail_rec_m::<OptionBrand, _, _>(
1288 |acc| {
1289 if acc < iterations {
1290 Some(ControlFlow::Continue(acc + 1))
1291 } else {
1292 Some(ControlFlow::Break(acc))
1293 }
1294 },
1295 0i64,
1296 );
1297 assert_eq!(result, Some(iterations));
1298 }
1299}