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