fp_library/types/option.rs
1use crate::{
2 Apply,
3 brands::OptionBrand,
4 classes::{
5 applicative::Applicative, apply_first::ApplyFirst, apply_second::ApplySecond,
6 cloneable_fn::CloneableFn, compactable::Compactable, filterable::Filterable,
7 foldable::Foldable, functor::Functor, lift::Lift, monoid::Monoid,
8 par_foldable::ParFoldable, pointed::Pointed, semiapplicative::Semiapplicative,
9 semimonad::Semimonad, send_cloneable_fn::SendCloneableFn, traversable::Traversable,
10 witherable::Witherable,
11 },
12 impl_kind,
13 kinds::*,
14 types::Pair,
15};
16
17impl_kind! {
18 for OptionBrand {
19 type Of<'a, A: 'a>: 'a = Option<A>;
20 }
21}
22
23impl Functor for OptionBrand {
24 /// Maps a function over the value in the option.
25 ///
26 /// This method applies a function to the value inside the option, producing a new option with the transformed value. If the option is `None`, it returns `None`.
27 ///
28 /// ### Type Signature
29 ///
30 /// `forall b a. Functor Option => (a -> b, Option a) -> Option b`
31 ///
32 /// ### Type Parameters
33 ///
34 /// * `B`: The type of the result of applying the function.
35 /// * `A`: The type of the value inside the option.
36 /// * `F`: The type of the function to apply.
37 ///
38 /// ### Parameters
39 ///
40 /// * `f`: The function to apply to the value.
41 /// * `fa`: The option to map over.
42 ///
43 /// ### Returns
44 ///
45 /// A new option containing the result of applying the function, or `None`.
46 ///
47 /// ### Examples
48 ///
49 /// ```
50 /// use fp_library::functions::*;
51 /// use fp_library::brands::OptionBrand;
52 ///
53 /// let x = Some(5);
54 /// let y = map::<OptionBrand, _, _, _>(|i| i * 2, x);
55 /// assert_eq!(y, Some(10));
56 /// ```
57 fn map<'a, B: 'a, A: 'a, F>(
58 f: F,
59 fa: Apply!(<Self as Kind!( type Of<'a, T: 'a>: 'a; )>::Of<'a, A>),
60 ) -> Apply!(<Self as Kind!( type Of<'a, T: 'a>: 'a; )>::Of<'a, B>)
61 where
62 F: Fn(A) -> B + 'a,
63 {
64 fa.map(f)
65 }
66}
67
68impl Lift for OptionBrand {
69 /// Lifts a binary function into the option context.
70 ///
71 /// This method lifts a binary function to operate on values within the option context.
72 ///
73 /// ### Type Signature
74 ///
75 /// `forall c a b. Lift Option => ((a, b) -> c, Option a, Option b) -> Option c`
76 ///
77 /// ### Type Parameters
78 ///
79 /// * `C`: The return type of the function.
80 /// * `A`: The type of the first option's value.
81 /// * `B`: The type of the second option's value.
82 /// * `F`: The type of the binary function.
83 ///
84 /// ### Parameters
85 ///
86 /// * `f`: The binary function to apply.
87 /// * `fa`: The first option.
88 /// * `fb`: The second option.
89 ///
90 /// ### Returns
91 ///
92 /// `Some(f(a, b))` if both options are `Some`, otherwise `None`.
93 ///
94 /// ### Examples
95 ///
96 /// ```
97 /// use fp_library::functions::*;
98 /// use fp_library::brands::OptionBrand;
99 ///
100 /// let x = Some(1);
101 /// let y = Some(2);
102 /// let z = lift2::<OptionBrand, _, _, _, _>(|a, b| a + b, x, y);
103 /// assert_eq!(z, Some(3));
104 /// ```
105 fn lift2<'a, C, A, B, F>(
106 f: F,
107 fa: Apply!(<Self as Kind!( type Of<'a, T: 'a>: 'a; )>::Of<'a, A>),
108 fb: Apply!(<Self as Kind!( type Of<'a, T: 'a>: 'a; )>::Of<'a, B>),
109 ) -> Apply!(<Self as Kind!( type Of<'a, T: 'a>: 'a; )>::Of<'a, C>)
110 where
111 F: Fn(A, B) -> C + 'a,
112 A: 'a,
113 B: 'a,
114 C: 'a,
115 {
116 fa.zip(fb).map(|(a, b)| f(a, b))
117 }
118}
119
120impl Pointed for OptionBrand {
121 /// Wraps a value in an option.
122 ///
123 /// This method wraps a value in an option context.
124 ///
125 /// ### Type Signature
126 ///
127 /// `forall a. Pointed Option => a -> Option a`
128 ///
129 /// ### Type Parameters
130 ///
131 /// * `A`: The type of the value to wrap.
132 ///
133 /// ### Parameters
134 ///
135 /// * `a`: The value to wrap.
136 ///
137 /// ### Returns
138 ///
139 /// `Some(a)`.
140 ///
141 /// ### Examples
142 ///
143 /// ```
144 /// use fp_library::functions::*;
145 /// use fp_library::brands::OptionBrand;
146 ///
147 /// let x = pure::<OptionBrand, _>(5);
148 /// assert_eq!(x, Some(5));
149 /// ```
150 fn pure<'a, A: 'a>(a: A) -> Apply!(<Self as Kind!( type Of<'a, T: 'a>: 'a; )>::Of<'a, A>) {
151 Some(a)
152 }
153}
154
155impl ApplyFirst for OptionBrand {}
156impl ApplySecond for OptionBrand {}
157
158impl Semiapplicative for OptionBrand {
159 /// Applies a wrapped function to a wrapped value.
160 ///
161 /// This method applies a function wrapped in an option to a value wrapped in an option.
162 ///
163 /// ### Type Signature
164 ///
165 /// `forall fn_brand b a. Semiapplicative Option => (Option (fn_brand a b), Option a) -> Option b`
166 ///
167 /// ### Type Parameters
168 ///
169 /// * `FnBrand`: The brand of the cloneable function wrapper.
170 /// * `B`: The type of the output value.
171 /// * `A`: The type of the input value.
172 ///
173 /// ### Parameters
174 ///
175 /// * `ff`: The option containing the function.
176 /// * `fa`: The option containing the value.
177 ///
178 /// ### Returns
179 ///
180 /// `Some(f(a))` if both are `Some`, otherwise `None`.
181 ///
182 /// ### Examples
183 ///
184 /// ```
185 /// use fp_library::{brands::*, classes::*, functions::*};
186 ///
187 /// let f = Some(cloneable_fn_new::<RcFnBrand, _, _>(|x: i32| x * 2));
188 /// let x = Some(5);
189 /// let y = apply::<RcFnBrand, OptionBrand, _, _>(f, x);
190 /// assert_eq!(y, Some(10));
191 /// ```
192 fn apply<'a, FnBrand: 'a + CloneableFn, B: 'a, A: 'a + Clone>(
193 ff: Apply!(<Self as Kind!( type Of<'a, T: 'a>: 'a; )>::Of<'a, <FnBrand as CloneableFn>::Of<'a, A, B>>),
194 fa: Apply!(<Self as Kind!( type Of<'a, T: 'a>: 'a; )>::Of<'a, A>),
195 ) -> Apply!(<Self as Kind!( type Of<'a, T: 'a>: 'a; )>::Of<'a, B>) {
196 match (ff, fa) {
197 (Some(f), Some(a)) => Some(f(a)),
198 _ => None,
199 }
200 }
201}
202
203impl Semimonad for OptionBrand {
204 /// Chains option computations.
205 ///
206 /// This method chains two option computations, where the second computation depends on the result of the first.
207 ///
208 /// ### Type Signature
209 ///
210 /// `forall b a. Semimonad Option => (Option a, a -> Option b) -> Option b`
211 ///
212 /// ### Type Parameters
213 ///
214 /// * `B`: The type of the result of the second computation.
215 /// * `A`: The type of the result of the first computation.
216 /// * `F`: The type of the function to apply.
217 ///
218 /// ### Parameters
219 ///
220 /// * `ma`: The first option.
221 /// * `f`: The function to apply to the value inside the option.
222 ///
223 /// ### Returns
224 ///
225 /// The result of applying `f` to the value if `ma` is `Some`, otherwise `None`.
226 ///
227 /// ### Examples
228 ///
229 /// ```
230 /// use fp_library::functions::*;
231 /// use fp_library::brands::OptionBrand;
232 ///
233 /// let x = Some(5);
234 /// let y = bind::<OptionBrand, _, _, _>(x, |i| Some(i * 2));
235 /// assert_eq!(y, Some(10));
236 /// ```
237 fn bind<'a, B: 'a, A: 'a, F>(
238 ma: Apply!(<Self as Kind!( type Of<'a, T: 'a>: 'a; )>::Of<'a, A>),
239 f: F,
240 ) -> Apply!(<Self as Kind!( type Of<'a, T: 'a>: 'a; )>::Of<'a, B>)
241 where
242 F: Fn(A) -> Apply!(<Self as Kind!( type Of<'a, T: 'a>: 'a; )>::Of<'a, B>) + 'a,
243 {
244 ma.and_then(f)
245 }
246}
247
248impl Foldable for OptionBrand {
249 /// Folds the option from the right.
250 ///
251 /// This method performs a right-associative fold of the option. If the option is `Some(a)`, it applies the function to `a` and the initial value. If `None`, it returns the initial value.
252 ///
253 /// ### Type Signature
254 ///
255 /// `forall b a. Foldable Option => ((a, b) -> b, b, Option a) -> b`
256 ///
257 /// ### Type Parameters
258 ///
259 /// * `FnBrand`: The brand of the cloneable function to use.
260 /// * `B`: The type of the accumulator.
261 /// * `A`: The type of the elements in the structure.
262 /// * `Func`: The type of the folding function.
263 ///
264 /// ### Parameters
265 ///
266 /// * `func`: The folding function.
267 /// * `initial`: The initial value.
268 /// * `fa`: The option to fold.
269 ///
270 /// ### Returns
271 ///
272 /// `func(a, initial)` if `fa` is `Some(a)`, otherwise `initial`.
273 ///
274 /// ### Examples
275 ///
276 /// ```
277 /// use fp_library::functions::*;
278 /// use fp_library::brands::{OptionBrand, RcFnBrand};
279 ///
280 /// let x = Some(5);
281 /// let y = fold_right::<RcFnBrand, OptionBrand, _, _, _>(|a, b| a + b, 10, x);
282 /// assert_eq!(y, 15);
283 /// ```
284 fn fold_right<'a, FnBrand, B: 'a, A: 'a, Func>(
285 func: Func,
286 initial: B,
287 fa: Apply!(<Self as Kind!( type Of<'a, T: 'a>: 'a; )>::Of<'a, A>),
288 ) -> B
289 where
290 Func: Fn(A, B) -> B + 'a,
291 FnBrand: CloneableFn + 'a,
292 {
293 match fa {
294 Some(a) => func(a, initial),
295 None => initial,
296 }
297 }
298
299 /// Folds the option from the left.
300 ///
301 /// This method performs a left-associative fold of the option. If the option is `Some(a)`, it applies the function to the initial value and `a`. If `None`, it returns the initial value.
302 ///
303 /// ### Type Signature
304 ///
305 /// `forall b a. Foldable Option => ((b, a) -> b, b, Option a) -> b`
306 ///
307 /// ### Type Parameters
308 ///
309 /// * `FnBrand`: The brand of the cloneable function to use.
310 /// * `B`: The type of the accumulator.
311 /// * `A`: The type of the elements in the structure.
312 /// * `Func`: The type of the folding function.
313 ///
314 /// ### Parameters
315 ///
316 /// * `func`: The function to apply to the accumulator and each element.
317 /// * `initial`: The initial value of the accumulator.
318 /// * `fa`: The option to fold.
319 ///
320 /// ### Returns
321 ///
322 /// `f(initial, a)` if `fa` is `Some(a)`, otherwise `initial`.
323 ///
324 /// ### Examples
325 ///
326 /// ```
327 /// use fp_library::functions::*;
328 /// use fp_library::brands::{OptionBrand, RcFnBrand};
329 ///
330 /// let x = Some(5);
331 /// let y = fold_left::<RcFnBrand, OptionBrand, _, _, _>(|b, a| b + a, 10, x);
332 /// assert_eq!(y, 15);
333 /// ```
334 fn fold_left<'a, FnBrand, B: 'a, A: 'a, Func>(
335 func: Func,
336 initial: B,
337 fa: Apply!(<Self as Kind!( type Of<'a, T: 'a>: 'a; )>::Of<'a, A>),
338 ) -> B
339 where
340 Func: Fn(B, A) -> B + 'a,
341 FnBrand: CloneableFn + 'a,
342 {
343 match fa {
344 Some(a) => func(initial, a),
345 None => initial,
346 }
347 }
348
349 /// Maps the value to a monoid and returns it, or returns empty.
350 ///
351 /// This method maps the element of the option to a monoid. If the option is `None`, it returns the monoid's identity element.
352 ///
353 /// ### Type Signature
354 ///
355 /// `forall m a. (Foldable Option, Monoid m) => ((a) -> m, Option a) -> m`
356 ///
357 /// ### Type Parameters
358 ///
359 /// * `FnBrand`: The brand of the cloneable function to use.
360 /// * `M`: The type of the monoid.
361 /// * `A`: The type of the elements in the structure.
362 /// * `Func`: The type of the mapping function.
363 ///
364 /// ### Parameters
365 ///
366 /// * `func`: The mapping function.
367 /// * `fa`: The option to fold.
368 ///
369 /// ### Returns
370 ///
371 /// `func(a)` if `fa` is `Some(a)`, otherwise `M::empty()`.
372 ///
373 /// ### Examples
374 ///
375 /// ```
376 /// use fp_library::{brands::*, functions::*, types::*};
377 ///
378 /// let x = Some(5);
379 /// let y = fold_map::<RcFnBrand, OptionBrand, _, _, _>(|a: i32| a.to_string(), x);
380 /// assert_eq!(y, "5".to_string());
381 /// ```
382 fn fold_map<'a, FnBrand, M, A: 'a, Func>(
383 func: Func,
384 fa: Apply!(<Self as Kind!( type Of<'a, T: 'a>: 'a; )>::Of<'a, A>),
385 ) -> M
386 where
387 M: Monoid + 'a,
388 Func: Fn(A) -> M + 'a,
389 FnBrand: CloneableFn + 'a,
390 {
391 match fa {
392 Some(a) => func(a),
393 None => M::empty(),
394 }
395 }
396}
397
398impl Traversable for OptionBrand {
399 /// Traverses the option with an applicative function.
400 ///
401 /// This method maps the element of the option to a computation, evaluates it, and wraps the result in the applicative context. If `None`, it returns `pure(None)`.
402 ///
403 /// ### Type Signature
404 ///
405 /// `forall f b a. (Traversable Option, Applicative f) => (a -> f b, Option a) -> f (Option b)`
406 ///
407 /// ### Type Parameters
408 ///
409 /// * `F`: The applicative context.
410 /// * `B`: The type of the elements in the resulting traversable structure.
411 /// * `A`: The type of the elements in the traversable structure.
412 /// * `Func`: The type of the function to apply.
413 ///
414 /// ### Parameters
415 ///
416 /// * `func`: The function to apply to each element, returning a value in an applicative context.
417 /// * `ta`: The option to traverse.
418 ///
419 /// ### Returns
420 ///
421 /// The option wrapped in the applicative context.
422 ///
423 /// ### Examples
424 ///
425 /// ```
426 /// use fp_library::functions::*;
427 /// use fp_library::brands::OptionBrand;
428 ///
429 /// let x = Some(5);
430 /// let y = traverse::<OptionBrand, OptionBrand, _, _, _>(|a| Some(a * 2), x);
431 /// assert_eq!(y, Some(Some(10)));
432 /// ```
433 fn traverse<'a, F: Applicative, B: 'a + Clone, A: 'a + Clone, Func>(
434 func: Func,
435 ta: Apply!(<Self as Kind!( type Of<'a, T: 'a>: 'a; )>::Of<'a, A>),
436 ) -> 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>)>)
437 where
438 Func: Fn(A) -> Apply!(<F as Kind!( type Of<'a, T: 'a>: 'a; )>::Of<'a, B>) + 'a,
439 Apply!(<Self as Kind!( type Of<'a, T: 'a>: 'a; )>::Of<'a, B>): Clone,
440 {
441 match ta {
442 Some(a) => F::map(|b| Some(b), func(a)),
443 None => F::pure(None),
444 }
445 }
446 /// Sequences an option of applicative.
447 ///
448 /// This method evaluates the computation inside the option and wraps the result in the applicative context. If `None`, it returns `pure(None)`.
449 ///
450 /// ### Type Signature
451 ///
452 /// `forall f a. (Traversable Option, Applicative f) => (Option (f a)) -> f (Option a)`
453 ///
454 /// ### Type Parameters
455 ///
456 /// * `F`: The applicative context.
457 /// * `A`: The type of the elements in the traversable structure.
458 ///
459 /// ### Parameters
460 ///
461 /// * `ta`: The option containing the applicative value.
462 ///
463 /// # Returns
464 ///
465 /// The option wrapped in the applicative context.
466 ///
467 /// ### Examples
468 ///
469 /// ```
470 /// use fp_library::functions::*;
471 /// use fp_library::brands::OptionBrand;
472 ///
473 /// let x = Some(Some(5));
474 /// let y = sequence::<OptionBrand, OptionBrand, _>(x);
475 /// assert_eq!(y, Some(Some(5)));
476 /// ```
477 fn sequence<'a, F: Applicative, A: 'a + Clone>(
478 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>)>)
479 ) -> 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>)>)
480 where
481 Apply!(<F as Kind!( type Of<'a, T: 'a>: 'a; )>::Of<'a, A>): Clone,
482 Apply!(<Self as Kind!( type Of<'a, T: 'a>: 'a; )>::Of<'a, A>): Clone,
483 {
484 match ta {
485 Some(fa) => F::map(|a| Some(a), fa),
486 None => F::pure(None),
487 }
488 }
489}
490
491impl<FnBrand: SendCloneableFn> ParFoldable<FnBrand> for OptionBrand {
492 /// Maps the value to a monoid and returns it, or returns empty, in parallel.
493 ///
494 /// This method maps the element of the option to a monoid. Since `Option` contains at most one element, no actual parallelism occurs, but the interface is satisfied.
495 ///
496 /// ### Type Signature
497 ///
498 /// `forall fn_brand m a. (ParFoldable Option, Monoid m, Send m, Sync m) => (fn_brand a m, Option a) -> m`
499 ///
500 /// ### Type Parameters
501 ///
502 /// * `M`: The monoid type (must be `Send + Sync`).
503 /// * `A`: The element type (must be `Send + Sync`).
504 ///
505 /// ### Parameters
506 ///
507 /// * `func`: The mapping function.
508 /// * `fa`: The option to fold.
509 ///
510 /// ### Returns
511 ///
512 /// The combined monoid value.
513 ///
514 /// ### Examples
515 ///
516 /// ```
517 /// use fp_library::functions::*;
518 /// use fp_library::brands::{OptionBrand, ArcFnBrand};
519 ///
520 /// let x = Some(1);
521 /// let f = send_cloneable_fn_new::<ArcFnBrand, _, _>(|x: i32| x.to_string());
522 /// let y = par_fold_map::<ArcFnBrand, OptionBrand, _, _>(f, x);
523 /// assert_eq!(y, "1".to_string());
524 /// ```
525 fn par_fold_map<'a, M, A>(
526 func: <FnBrand as SendCloneableFn>::SendOf<'a, A, M>,
527 fa: Apply!(<Self as Kind!( type Of<'a, T: 'a>: 'a; )>::Of<'a, A>),
528 ) -> M
529 where
530 A: 'a + Clone + Send + Sync,
531 M: Monoid + Send + Sync + 'a,
532 {
533 match fa {
534 Some(a) => func(a),
535 None => M::empty(),
536 }
537 }
538}
539
540impl Compactable for OptionBrand {
541 /// Compacts a nested option.
542 ///
543 /// This method flattens a nested option.
544 ///
545 /// ### Type Signature
546 ///
547 /// `forall a. Compactable Option => Option (Option a) -> Option a`
548 ///
549 /// ### Type Parameters
550 ///
551 /// * `A`: The type of the elements.
552 ///
553 /// ### Parameters
554 ///
555 /// * `fa`: The nested option.
556 ///
557 /// ### Returns
558 ///
559 /// The flattened option.
560 ///
561 /// ### Examples
562 ///
563 /// ```
564 /// use fp_library::functions::*;
565 /// use fp_library::brands::OptionBrand;
566 ///
567 /// let x = Some(Some(5));
568 /// let y = compact::<OptionBrand, _>(x);
569 /// assert_eq!(y, Some(5));
570 /// ```
571 fn compact<'a, A: 'a>(
572 fa: Apply!(<Self as Kind!( type Of<'a, T: 'a>: 'a; )>::Of<
573 'a,
574 Apply!(<OptionBrand as Kind!( type Of<'a, T: 'a>: 'a; )>::Of<'a, A>),
575 >)
576 ) -> Apply!(<Self as Kind!( type Of<'a, T: 'a>: 'a; )>::Of<'a, A>) {
577 fa.flatten()
578 }
579
580 /// Separates an option of result.
581 ///
582 /// This method separates an option of result into a pair of options.
583 ///
584 /// ### Type Signature
585 ///
586 /// `forall o e. Compactable Option => Option (Result o e) -> (Option o, Option e)`
587 ///
588 /// ### Type Parameters
589 ///
590 /// * `O`: The type of the success value.
591 /// * `E`: The type of the error value.
592 ///
593 /// ### Parameters
594 ///
595 /// * `fa`: The option of result.
596 ///
597 /// ### Returns
598 ///
599 /// A pair of options.
600 ///
601 /// ### Examples
602 ///
603 /// ```
604 /// use fp_library::{brands::*, functions::*, types::*};
605 ///
606 /// let x: Option<Result<i32, &str>> = Some(Ok(5));
607 /// let Pair(oks, errs) = separate::<OptionBrand, _, _>(x);
608 /// assert_eq!(oks, Some(5));
609 /// assert_eq!(errs, None);
610 /// ```
611 fn separate<'a, O: 'a, E: 'a>(
612 fa: Apply!(<Self as Kind!( type Of<'a, T: 'a>: 'a; )>::Of<'a, Result<O, E>>)
613 ) -> Pair<
614 Apply!(<Self as Kind!( type Of<'a, T: 'a>: 'a; )>::Of<'a, O>),
615 Apply!(<Self as Kind!( type Of<'a, T: 'a>: 'a; )>::Of<'a, E>),
616 > {
617 match fa {
618 Some(Ok(o)) => Pair(Some(o), None),
619 Some(Err(e)) => Pair(None, Some(e)),
620 None => Pair(None, None),
621 }
622 }
623}
624
625impl Filterable for OptionBrand {
626 /// Partitions an option based on a function that returns a result.
627 ///
628 /// This method partitions an option based on a function that returns a result.
629 ///
630 /// ### Type Signature
631 ///
632 /// `forall o e a. Filterable Option => (a -> Result o e, Option a) -> Pair (Option o) (Option e)`
633 ///
634 /// ### Type Parameters
635 ///
636 /// * `O`: The type of the success value.
637 /// * `E`: The type of the error value.
638 /// * `A`: The type of the input value.
639 /// * `Func`: The type of the function to apply.
640 ///
641 /// ### Parameters
642 ///
643 /// * `func`: The function to apply.
644 /// * `fa`: The option to partition.
645 ///
646 /// ### Returns
647 ///
648 /// A pair of options.
649 ///
650 /// ### Examples
651 ///
652 /// ```
653 /// use fp_library::{brands::*, functions::*, types::*};
654 ///
655 /// let x = Some(5);
656 /// let Pair(oks, errs) = partition_map::<OptionBrand, _, _, _, _>(|a| if a > 2 { Ok(a) } else { Err(a) }, x);
657 /// assert_eq!(oks, Some(5));
658 /// assert_eq!(errs, None);
659 /// ```
660 fn partition_map<'a, O: 'a, E: 'a, A: 'a, Func>(
661 func: Func,
662 fa: Apply!(<Self as Kind!( type Of<'a, T: 'a>: 'a; )>::Of<'a, A>),
663 ) -> Pair<
664 Apply!(<Self as Kind!( type Of<'a, T: 'a>: 'a; )>::Of<'a, O>),
665 Apply!(<Self as Kind!( type Of<'a, T: 'a>: 'a; )>::Of<'a, E>),
666 >
667 where
668 Func: Fn(A) -> Result<O, E> + 'a,
669 {
670 match fa {
671 Some(a) => match func(a) {
672 Ok(o) => Pair(Some(o), None),
673 Err(e) => Pair(None, Some(e)),
674 },
675 None => Pair(None, None),
676 }
677 }
678 /// Partitions an option based on a predicate.
679 ///
680 /// This method partitions an option based on a predicate.
681 ///
682 /// ### Type Signature
683 ///
684 /// `forall a. Filterable Option => (a -> bool, Option a) -> Pair (Option a) (Option a)`
685 ///
686 /// ### Type Parameters
687 ///
688 /// * `A`: The type of the elements.
689 /// * `Func`: The type of the predicate.
690 ///
691 /// ### Parameters
692 ///
693 /// * `func`: The predicate.
694 /// * `fa`: The option to partition.
695 ///
696 /// ### Returns
697 ///
698 /// A pair of options.
699 ///
700 /// ### Examples
701 ///
702 /// ```
703 /// use fp_library::{brands::*, functions::*, types::*};
704 ///
705 /// let x = Some(5);
706 /// let Pair(satisfied, not_satisfied) = partition::<OptionBrand, _, _>(|a| a > 2, x);
707 /// assert_eq!(satisfied, Some(5));
708 /// assert_eq!(not_satisfied, None);
709 /// ```
710 fn partition<'a, A: 'a + Clone, Func>(
711 func: Func,
712 fa: Apply!(<Self as Kind!( type Of<'a, T: 'a>: 'a; )>::Of<'a, A>),
713 ) -> Pair<
714 Apply!(<Self as Kind!( type Of<'a, T: 'a>: 'a; )>::Of<'a, A>),
715 Apply!(<Self as Kind!( type Of<'a, T: 'a>: 'a; )>::Of<'a, A>),
716 >
717 where
718 Func: Fn(A) -> bool + 'a,
719 {
720 match fa {
721 Some(a) => {
722 if func(a.clone()) {
723 Pair(Some(a), None)
724 } else {
725 Pair(None, Some(a))
726 }
727 }
728 None => Pair(None, None),
729 }
730 }
731
732 /// Maps a function over an option and filters out `None` results.
733 ///
734 /// This method maps a function over an option and filters out `None` results.
735 ///
736 /// ### Type Signature
737 ///
738 /// `forall b a. Filterable Option => (a -> Option b, Option a) -> Option b`
739 ///
740 /// ### Type Parameters
741 ///
742 /// * `B`: The type of the result of applying the function.
743 /// * `A`: The type of the input value.
744 /// * `Func`: The type of the function to apply.
745 ///
746 /// ### Parameters
747 ///
748 /// * `func`: The function to apply.
749 /// * `fa`: The option to filter and map.
750 ///
751 /// ### Returns
752 ///
753 /// The filtered and mapped option.
754 ///
755 /// ### Examples
756 ///
757 /// ```
758 /// use fp_library::functions::*;
759 /// use fp_library::brands::OptionBrand;
760 ///
761 /// let x = Some(5);
762 /// let y = filter_map::<OptionBrand, _, _, _>(|a| if a > 2 { Some(a * 2) } else { None }, x);
763 /// assert_eq!(y, Some(10));
764 /// ```
765 fn filter_map<'a, B: 'a, A: 'a, Func>(
766 func: Func,
767 fa: Apply!(<Self as Kind!( type Of<'a, T: 'a>: 'a; )>::Of<'a, A>),
768 ) -> Apply!(<Self as Kind!( type Of<'a, T: 'a>: 'a; )>::Of<'a, B>)
769 where
770 Func: Fn(A) -> Option<B> + 'a,
771 {
772 fa.and_then(func)
773 }
774
775 /// Filters an option based on a predicate.
776 ///
777 /// This method filters an option based on a predicate.
778 ///
779 /// ### Type Signature
780 ///
781 /// `forall a. Filterable Option => (a -> bool, Option a) -> Option a`
782 ///
783 /// ### Type Parameters
784 ///
785 /// * `A`: The type of the elements.
786 /// * `Func`: The type of the predicate.
787 ///
788 /// ### Parameters
789 ///
790 /// * `func`: The predicate.
791 /// * `fa`: The option to filter.
792 ///
793 /// ### Returns
794 ///
795 /// The filtered option.
796 ///
797 /// ### Examples
798 ///
799 /// ```
800 /// use fp_library::functions::*;
801 /// use fp_library::brands::OptionBrand;
802 ///
803 /// let x = Some(5);
804 /// let y = filter::<OptionBrand, _, _>(|a| a > 2, x);
805 /// assert_eq!(y, Some(5));
806 /// ```
807 fn filter<'a, A: 'a + Clone, Func>(
808 func: Func,
809 fa: Apply!(<Self as Kind!( type Of<'a, T: 'a>: 'a; )>::Of<'a, A>),
810 ) -> Apply!(<Self as Kind!( type Of<'a, T: 'a>: 'a; )>::Of<'a, A>)
811 where
812 Func: Fn(A) -> bool + 'a,
813 {
814 fa.filter(|a| func(a.clone()))
815 }
816}
817
818impl Witherable for OptionBrand {
819 /// Partitions an option based on a function that returns a result in an applicative context.
820 ///
821 /// This method partitions an option based on a function that returns a result in an applicative context.
822 ///
823 /// ### Type Signature
824 ///
825 /// `forall m o e a. (Witherable Option, Applicative m) => (a -> m (Result o e), Option a) -> m (Pair (Option o) (Option e))`
826 ///
827 /// ### Type Parameters
828 ///
829 /// * `M`: The applicative context.
830 /// * `O`: The type of the success values.
831 /// * `E`: The type of the error values.
832 /// * `A`: The type of the elements in the input structure.
833 /// * `Func`: The type of the function to apply.
834 ///
835 /// ### Parameters
836 ///
837 /// * `func`: The function to apply to each element, returning a `Result` in an applicative context.
838 /// * `ta`: The option to partition.
839 ///
840 /// ### Returns
841 ///
842 /// The partitioned option wrapped in the applicative context.
843 ///
844 /// ### Examples
845 ///
846 /// ```
847 /// use fp_library::{functions::*, brands::*, types::*};
848 ///
849 /// let x = Some(5);
850 /// let y = wilt::<OptionBrand, OptionBrand, _, _, _, _>(|a| Some(if a > 2 { Ok(a) } else { Err(a) }), x);
851 /// assert_eq!(y, Some(Pair(Some(5), None)));
852 /// ```
853 fn wilt<'a, M: Applicative, O: 'a + Clone, E: 'a + Clone, A: 'a + Clone, Func>(
854 func: Func,
855 ta: Apply!(<Self as Kind!( type Of<'a, T: 'a>: 'a; )>::Of<'a, A>),
856 ) -> Apply!(<M as Kind!( type Of<'a, T: 'a>: 'a; )>::Of<
857 'a,
858 Pair<
859 Apply!(<Self as Kind!( type Of<'a, T: 'a>: 'a; )>::Of<'a, O>),
860 Apply!(<Self as Kind!( type Of<'a, T: 'a>: 'a; )>::Of<'a, E>),
861 >,
862 >)
863 where
864 Func: Fn(A) -> Apply!(<M as Kind!( type Of<'a, T: 'a>: 'a; )>::Of<'a, Result<O, E>>) + 'a,
865 Apply!(<Self as Kind!( type Of<'a, T: 'a>: 'a; )>::Of<'a, Result<O, E>>): Clone,
866 Apply!(<M as Kind!( type Of<'a, T: 'a>: 'a; )>::Of<'a, Result<O, E>>): Clone,
867 {
868 match ta {
869 Some(a) => M::map(
870 |res| match res {
871 Ok(o) => Pair(Some(o), None),
872 Err(e) => Pair(None, Some(e)),
873 },
874 func(a),
875 ),
876 None => M::pure(Pair(None, None)),
877 }
878 }
879
880 /// Maps a function over an option and filters out `None` results in an applicative context.
881 ///
882 /// This method maps a function over an option and filters out `None` results in an applicative context.
883 ///
884 /// ### Type Signature
885 ///
886 /// `forall m b a. (Witherable Option, Applicative m) => (a -> m (Option b), Option a) -> m (Option b)`
887 ///
888 /// ### Type Parameters
889 ///
890 /// * `M`: The applicative context.
891 /// * `B`: The type of the result of applying the function.
892 /// * `A`: The type of the elements in the input structure.
893 /// * `Func`: The type of the function to apply.
894 ///
895 /// ### Parameters
896 ///
897 /// * `func`: The function to apply to each element, returning an `Option` in an applicative context.
898 /// * `ta`: The option to filter and map.
899 ///
900 /// ### Returns
901 ///
902 /// The filtered and mapped option wrapped in the applicative context.
903 ///
904 /// ### Examples
905 ///
906 /// ```
907 /// use fp_library::{functions::*, brands::*};
908 ///
909 /// let x = Some(5);
910 /// let y = wither::<OptionBrand, OptionBrand, _, _, _>(|a| Some(if a > 2 { Some(a * 2) } else { None }), x);
911 /// assert_eq!(y, Some(Some(10)));
912 /// ```
913 fn wither<'a, M: Applicative, B: 'a + Clone, A: 'a + Clone, Func>(
914 func: Func,
915 ta: Apply!(<Self as Kind!( type Of<'a, T: 'a>: 'a; )>::Of<'a, A>),
916 ) -> Apply!(<M as Kind!( type Of<'a, T: 'a>: 'a; )>::Of<
917 'a,
918 Apply!(<Self as Kind!( type Of<'a, T: 'a>: 'a; )>::Of<'a, B>),
919 >)
920 where
921 Func: Fn(A) -> Apply!(<M as Kind!( type Of<'a, T: 'a>: 'a; )>::Of<'a, Option<B>>) + 'a,
922 Apply!(<Self as Kind!( type Of<'a, T: 'a>: 'a; )>::Of<'a, Option<B>>): Clone,
923 Apply!(<M as Kind!( type Of<'a, T: 'a>: 'a; )>::Of<'a, Option<B>>): Clone,
924 {
925 match ta {
926 Some(a) => func(a),
927 None => M::pure(None),
928 }
929 }
930}
931
932#[cfg(test)]
933mod tests {
934 use super::*;
935 use crate::{brands::*, functions::*};
936 use quickcheck_macros::quickcheck;
937
938 // Functor Laws
939
940 /// Tests the identity law for Functor.
941 #[quickcheck]
942 fn functor_identity(x: Option<i32>) -> bool {
943 map::<OptionBrand, _, _, _>(identity, x) == x
944 }
945
946 /// Tests the composition law for Functor.
947 #[quickcheck]
948 fn functor_composition(x: Option<i32>) -> bool {
949 let f = |x: i32| x.wrapping_add(1);
950 let g = |x: i32| x.wrapping_mul(2);
951 map::<OptionBrand, _, _, _>(compose(f, g), x)
952 == map::<OptionBrand, _, _, _>(f, map::<OptionBrand, _, _, _>(g, x))
953 }
954
955 // Applicative Laws
956
957 /// Tests the identity law for Applicative.
958 #[quickcheck]
959 fn applicative_identity(v: Option<i32>) -> bool {
960 apply::<RcFnBrand, OptionBrand, _, _>(
961 pure::<OptionBrand, _>(<RcFnBrand as CloneableFn>::new(identity)),
962 v,
963 ) == v
964 }
965
966 /// Tests the homomorphism law for Applicative.
967 #[quickcheck]
968 fn applicative_homomorphism(x: i32) -> bool {
969 let f = |x: i32| x.wrapping_mul(2);
970 apply::<RcFnBrand, OptionBrand, _, _>(
971 pure::<OptionBrand, _>(<RcFnBrand as CloneableFn>::new(f)),
972 pure::<OptionBrand, _>(x),
973 ) == pure::<OptionBrand, _>(f(x))
974 }
975
976 /// Tests the composition law for Applicative.
977 #[quickcheck]
978 fn applicative_composition(
979 w: Option<i32>,
980 u_is_some: bool,
981 v_is_some: bool,
982 ) -> bool {
983 let v_fn = |x: i32| x.wrapping_mul(2);
984 let u_fn = |x: i32| x.wrapping_add(1);
985
986 let v = if v_is_some {
987 pure::<OptionBrand, _>(<RcFnBrand as CloneableFn>::new(v_fn))
988 } else {
989 None
990 };
991 let u = if u_is_some {
992 pure::<OptionBrand, _>(<RcFnBrand as CloneableFn>::new(u_fn))
993 } else {
994 None
995 };
996
997 // RHS: u <*> (v <*> w)
998 let vw = apply::<RcFnBrand, OptionBrand, _, _>(v.clone(), w.clone());
999 let rhs = apply::<RcFnBrand, OptionBrand, _, _>(u.clone(), vw);
1000
1001 // LHS: pure(compose) <*> u <*> v <*> w
1002 // equivalent to (u . v) <*> w
1003 let uv = match (u, v) {
1004 (Some(uf), Some(vf)) => {
1005 let composed = move |x| uf(vf(x));
1006 Some(<RcFnBrand as CloneableFn>::new(composed))
1007 }
1008 _ => None,
1009 };
1010
1011 let lhs = apply::<RcFnBrand, OptionBrand, _, _>(uv, w);
1012
1013 lhs == rhs
1014 }
1015
1016 /// Tests the interchange law for Applicative.
1017 #[quickcheck]
1018 fn applicative_interchange(y: i32) -> bool {
1019 // u <*> pure y = pure ($ y) <*> u
1020 let f = |x: i32| x.wrapping_mul(2);
1021 let u = pure::<OptionBrand, _>(<RcFnBrand as CloneableFn>::new(f));
1022
1023 let lhs = apply::<RcFnBrand, OptionBrand, _, _>(u.clone(), pure::<OptionBrand, _>(y));
1024
1025 let rhs_fn =
1026 <RcFnBrand as CloneableFn>::new(move |f: std::rc::Rc<dyn Fn(i32) -> i32>| f(y));
1027 let rhs = apply::<RcFnBrand, OptionBrand, _, _>(pure::<OptionBrand, _>(rhs_fn), u);
1028
1029 lhs == rhs
1030 }
1031
1032 // Monad Laws
1033
1034 /// Tests the left identity law for Monad.
1035 #[quickcheck]
1036 fn monad_left_identity(a: i32) -> bool {
1037 let f = |x: i32| Some(x.wrapping_mul(2));
1038 bind::<OptionBrand, _, _, _>(pure::<OptionBrand, _>(a), f) == f(a)
1039 }
1040
1041 /// Tests the right identity law for Monad.
1042 #[quickcheck]
1043 fn monad_right_identity(m: Option<i32>) -> bool {
1044 bind::<OptionBrand, _, _, _>(m, pure::<OptionBrand, _>) == m
1045 }
1046
1047 /// Tests the associativity law for Monad.
1048 #[quickcheck]
1049 fn monad_associativity(m: Option<i32>) -> bool {
1050 let f = |x: i32| Some(x.wrapping_mul(2));
1051 let g = |x: i32| Some(x.wrapping_add(1));
1052 bind::<OptionBrand, _, _, _>(bind::<OptionBrand, _, _, _>(m, f), g)
1053 == bind::<OptionBrand, _, _, _>(m, |x| bind::<OptionBrand, _, _, _>(f(x), g))
1054 }
1055
1056 // Edge Cases
1057
1058 /// Tests `map` on `None`.
1059 #[test]
1060 fn map_none() {
1061 assert_eq!(map::<OptionBrand, _, _, _>(|x: i32| x + 1, None), None);
1062 }
1063
1064 /// Tests `bind` on `None`.
1065 #[test]
1066 fn bind_none() {
1067 assert_eq!(bind::<OptionBrand, _, _, _>(None, |x: i32| Some(x + 1)), None);
1068 }
1069
1070 /// Tests `bind` returning `None`.
1071 #[test]
1072 fn bind_returning_none() {
1073 assert_eq!(bind::<OptionBrand, _, _, _>(Some(5), |_| None::<i32>), None);
1074 }
1075
1076 /// Tests `fold_right` on `None`.
1077 #[test]
1078 fn fold_right_none() {
1079 assert_eq!(
1080 crate::classes::foldable::fold_right::<RcFnBrand, OptionBrand, _, _, _>(
1081 |x: i32, acc| x + acc,
1082 0,
1083 None
1084 ),
1085 0
1086 );
1087 }
1088
1089 /// Tests `fold_left` on `None`.
1090 #[test]
1091 fn fold_left_none() {
1092 assert_eq!(
1093 crate::classes::foldable::fold_left::<RcFnBrand, OptionBrand, _, _, _>(
1094 |acc, x: i32| acc + x,
1095 0,
1096 None
1097 ),
1098 0
1099 );
1100 }
1101
1102 /// Tests `traverse` on `None`.
1103 #[test]
1104 fn traverse_none() {
1105 assert_eq!(
1106 crate::classes::traversable::traverse::<OptionBrand, OptionBrand, _, _, _>(
1107 |x: i32| Some(x + 1),
1108 None
1109 ),
1110 Some(None)
1111 );
1112 }
1113
1114 /// Tests `traverse` returning `None`.
1115 #[test]
1116 fn traverse_returning_none() {
1117 assert_eq!(
1118 crate::classes::traversable::traverse::<OptionBrand, OptionBrand, _, _, _>(
1119 |_: i32| None::<i32>,
1120 Some(5)
1121 ),
1122 None
1123 );
1124 }
1125
1126 // ParFoldable Tests
1127
1128 /// Tests `par_fold_map` on `None`.
1129 #[test]
1130 fn par_fold_map_none() {
1131 let x: Option<i32> = None;
1132 let f = send_cloneable_fn_new::<ArcFnBrand, _, _>(|x: i32| x.to_string());
1133 assert_eq!(par_fold_map::<ArcFnBrand, OptionBrand, _, _>(f, x), "".to_string());
1134 }
1135
1136 /// Tests `par_fold_map` on `Some`.
1137 #[test]
1138 fn par_fold_map_some() {
1139 let x = Some(5);
1140 let f = send_cloneable_fn_new::<ArcFnBrand, _, _>(|x: i32| x.to_string());
1141 assert_eq!(par_fold_map::<ArcFnBrand, OptionBrand, _, _>(f, x), "5".to_string());
1142 }
1143
1144 /// Tests `par_fold_right` on `Some`.
1145 #[test]
1146 fn par_fold_right_some() {
1147 let x = Some(5);
1148 let f = send_cloneable_fn_new::<ArcFnBrand, _, _>(|(a, b): (i32, i32)| a + b);
1149 assert_eq!(par_fold_right::<ArcFnBrand, OptionBrand, _, _>(f, 10, x), 15);
1150 }
1151
1152 // Filterable Laws
1153
1154 /// Tests `filterMap identity ≡ compact`.
1155 #[quickcheck]
1156 fn filterable_filter_map_identity(x: Option<Option<i32>>) -> bool {
1157 filter_map::<OptionBrand, _, _, _>(identity, x.clone()) == compact::<OptionBrand, _>(x)
1158 }
1159
1160 /// Tests `filterMap Just ≡ identity`.
1161 #[quickcheck]
1162 fn filterable_filter_map_just(x: Option<i32>) -> bool {
1163 filter_map::<OptionBrand, _, _, _>(Some, x.clone()) == x
1164 }
1165
1166 /// Tests `filterMap (l <=< r) ≡ filterMap l <<< filterMap r`.
1167 #[quickcheck]
1168 fn filterable_filter_map_composition(x: Option<i32>) -> bool {
1169 let r = |i: i32| if i % 2 == 0 { Some(i) } else { None };
1170 let l = |i: i32| if i > 5 { Some(i) } else { None };
1171 let composed = |i| r(i).and_then(l);
1172
1173 filter_map::<OptionBrand, _, _, _>(composed, x.clone())
1174 == filter_map::<OptionBrand, _, _, _>(l, filter_map::<OptionBrand, _, _, _>(r, x))
1175 }
1176
1177 /// Tests `filter ≡ filterMap <<< maybeBool`.
1178 #[quickcheck]
1179 fn filterable_filter_consistency(x: Option<i32>) -> bool {
1180 let p = |i: i32| i % 2 == 0;
1181 let maybe_bool = |i| if p(i) { Some(i) } else { None };
1182
1183 filter::<OptionBrand, _, _>(p, x.clone())
1184 == filter_map::<OptionBrand, _, _, _>(maybe_bool, x)
1185 }
1186
1187 /// Tests `partitionMap identity ≡ separate`.
1188 #[quickcheck]
1189 fn filterable_partition_map_identity(x: Option<Result<i32, i32>>) -> bool {
1190 partition_map::<OptionBrand, _, _, _, _>(identity, x.clone())
1191 == separate::<OptionBrand, _, _>(x)
1192 }
1193
1194 /// Tests `partitionMap Right ≡ identity` (on the right side).
1195 #[quickcheck]
1196 fn filterable_partition_map_right_identity(x: Option<i32>) -> bool {
1197 let Pair(oks, _) = partition_map::<OptionBrand, _, _, _, _>(Ok::<_, i32>, x.clone());
1198 oks == x
1199 }
1200
1201 /// Tests `partitionMap Left ≡ identity` (on the left side).
1202 #[quickcheck]
1203 fn filterable_partition_map_left_identity(x: Option<i32>) -> bool {
1204 let Pair(_, errs) = partition_map::<OptionBrand, _, _, _, _>(Err::<i32, _>, x.clone());
1205 errs == x
1206 }
1207
1208 /// Tests `f <<< partition ≡ partitionMap <<< eitherBool`.
1209 #[quickcheck]
1210 fn filterable_partition_consistency(x: Option<i32>) -> bool {
1211 let p = |i: i32| i % 2 == 0;
1212 let either_bool = |i| if p(i) { Ok(i) } else { Err(i) };
1213
1214 let Pair(satisfied, not_satisfied) = partition::<OptionBrand, _, _>(p, x.clone());
1215 let Pair(oks, errs) = partition_map::<OptionBrand, _, _, _, _>(either_bool, x);
1216
1217 satisfied == oks && not_satisfied == errs
1218 }
1219
1220 // Witherable Laws
1221
1222 /// Tests `wither (pure <<< Just) ≡ pure`.
1223 #[quickcheck]
1224 fn witherable_identity(x: Option<i32>) -> bool {
1225 wither::<OptionBrand, OptionBrand, _, _, _>(|i| Some(Some(i)), x.clone()) == Some(x)
1226 }
1227
1228 /// Tests `wilt p ≡ map separate <<< traverse p`.
1229 #[quickcheck]
1230 fn witherable_wilt_consistency(x: Option<i32>) -> bool {
1231 let p = |i: i32| Some(if i % 2 == 0 { Ok(i) } else { Err(i) });
1232
1233 let lhs = wilt::<OptionBrand, OptionBrand, _, _, _, _>(p, x.clone());
1234 let rhs = map::<OptionBrand, _, _, _>(
1235 |res| separate::<OptionBrand, _, _>(res),
1236 traverse::<OptionBrand, OptionBrand, _, _, _>(p, x),
1237 );
1238
1239 lhs == rhs
1240 }
1241
1242 /// Tests `wither p ≡ map compact <<< traverse p`.
1243 #[quickcheck]
1244 fn witherable_wither_consistency(x: Option<i32>) -> bool {
1245 let p = |i: i32| Some(if i % 2 == 0 { Some(i) } else { None });
1246
1247 let lhs = wither::<OptionBrand, OptionBrand, _, _, _>(p, x.clone());
1248 let rhs = map::<OptionBrand, _, _, _>(
1249 |opt| compact::<OptionBrand, _>(opt),
1250 traverse::<OptionBrand, OptionBrand, _, _, _>(p, x),
1251 );
1252
1253 lhs == rhs
1254 }
1255
1256 // Edge Cases
1257
1258 /// Tests `compact` on `Some(None)`.
1259 #[test]
1260 fn compact_some_none() {
1261 assert_eq!(compact::<OptionBrand, _>(Some(None::<i32>)), None);
1262 }
1263
1264 /// Tests `compact` on `Some(Some(x))`.
1265 #[test]
1266 fn compact_some_some() {
1267 assert_eq!(compact::<OptionBrand, _>(Some(Some(5))), Some(5));
1268 }
1269
1270 /// Tests `compact` on `None`.
1271 #[test]
1272 fn compact_none() {
1273 assert_eq!(compact::<OptionBrand, _>(None::<Option<i32>>), None);
1274 }
1275
1276 /// Tests `separate` on `Some(Ok(x))`.
1277 #[test]
1278 fn separate_some_ok() {
1279 let Pair(oks, errs) = separate::<OptionBrand, _, _>(Some(Ok::<i32, &str>(5)));
1280 assert_eq!(oks, Some(5));
1281 assert_eq!(errs, None);
1282 }
1283
1284 /// Tests `separate` on `Some(Err(e))`.
1285 #[test]
1286 fn separate_some_err() {
1287 let Pair(oks, errs) = separate::<OptionBrand, _, _>(Some(Err::<i32, &str>("error")));
1288 assert_eq!(oks, None);
1289 assert_eq!(errs, Some("error"));
1290 }
1291
1292 /// Tests `separate` on `None`.
1293 #[test]
1294 fn separate_none() {
1295 let Pair(oks, errs) = separate::<OptionBrand, _, _>(None::<Result<i32, &str>>);
1296 assert_eq!(oks, None);
1297 assert_eq!(errs, None);
1298 }
1299
1300 /// Tests `partition_map` on `None`.
1301 #[test]
1302 fn partition_map_none() {
1303 let Pair(oks, errs) =
1304 partition_map::<OptionBrand, _, _, _, _>(|x: i32| Ok::<i32, i32>(x), None::<i32>);
1305 assert_eq!(oks, None);
1306 assert_eq!(errs, None);
1307 }
1308
1309 /// Tests `partition` on `None`.
1310 #[test]
1311 fn partition_none() {
1312 let Pair(satisfied, not_satisfied) =
1313 partition::<OptionBrand, _, _>(|x: i32| x > 0, None::<i32>);
1314 assert_eq!(satisfied, None);
1315 assert_eq!(not_satisfied, None);
1316 }
1317
1318 /// Tests `filter_map` on `None`.
1319 #[test]
1320 fn filter_map_none() {
1321 assert_eq!(filter_map::<OptionBrand, _, _, _>(|x: i32| Some(x), None::<i32>), None);
1322 }
1323
1324 /// Tests `filter` on `None`.
1325 #[test]
1326 fn filter_none() {
1327 assert_eq!(filter::<OptionBrand, _, _>(|x: i32| x > 0, None::<i32>), None);
1328 }
1329
1330 /// Tests `wilt` on `None`.
1331 #[test]
1332 fn wilt_none() {
1333 let res = wilt::<OptionBrand, OptionBrand, _, _, _, _>(
1334 |x: i32| Some(Ok::<i32, i32>(x)),
1335 None::<i32>,
1336 );
1337 assert_eq!(res, Some(Pair(None, None)));
1338 }
1339
1340 /// Tests `wither` on `None`.
1341 #[test]
1342 fn wither_none() {
1343 let res = wither::<OptionBrand, OptionBrand, _, _, _>(|x: i32| Some(Some(x)), None::<i32>);
1344 assert_eq!(res, Some(None));
1345 }
1346}