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 clonable_fn::ClonableFn, 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_clonable_fn::SendClonableFn, 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 clonable 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(clonable_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 + ClonableFn, B: 'a, A: 'a + Clone>(
197 ff: Apply!(<Self as Kind!( type Of<'a, T: 'a>: 'a; )>::Of<'a, <FnBrand as ClonableFn>::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 clonable 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: ClonableFn + '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 clonable 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: ClonableFn + '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 clonable 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::functions::*;
381 /// use fp_library::brands::{OptionBrand, RcFnBrand};
382 /// use fp_library::types::string; // Import to bring Monoid impl for String into scope
383 ///
384 /// let x = Some(5);
385 /// let y = fold_map::<RcFnBrand, OptionBrand, _, _, _>(|a: i32| a.to_string(), x);
386 /// assert_eq!(y, "5".to_string());
387 /// ```
388 fn fold_map<'a, FnBrand, M, A: 'a, Func>(
389 func: Func,
390 fa: Apply!(<Self as Kind!( type Of<'a, T: 'a>: 'a; )>::Of<'a, A>),
391 ) -> M
392 where
393 M: Monoid + 'a,
394 Func: Fn(A) -> M + 'a,
395 FnBrand: ClonableFn + 'a,
396 {
397 match fa {
398 Some(a) => func(a),
399 None => M::empty(),
400 }
401 }
402}
403
404impl Traversable for OptionBrand {
405 /// Traverses the option with an applicative function.
406 ///
407 /// 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)`.
408 ///
409 /// ### Type Signature
410 ///
411 /// `forall f b a. (Traversable Option, Applicative f) => (a -> f b, Option a) -> f (Option b)`
412 ///
413 /// ### Type Parameters
414 ///
415 /// * `F`: The applicative context.
416 /// * `B`: The type of the elements in the resulting traversable structure.
417 /// * `A`: The type of the elements in the traversable structure.
418 /// * `Func`: The type of the function to apply.
419 ///
420 /// ### Parameters
421 ///
422 /// * `func`: The function to apply to each element, returning a value in an applicative context.
423 /// * `ta`: The option to traverse.
424 ///
425 /// ### Returns
426 ///
427 /// The option wrapped in the applicative context.
428 ///
429 /// ### Examples
430 ///
431 /// ```
432 /// use fp_library::functions::*;
433 /// use fp_library::brands::OptionBrand;
434 ///
435 /// let x = Some(5);
436 /// let y = traverse::<OptionBrand, OptionBrand, _, _, _>(|a| Some(a * 2), x);
437 /// assert_eq!(y, Some(Some(10)));
438 /// ```
439 fn traverse<'a, F: Applicative, B: 'a + Clone, A: 'a + Clone, Func>(
440 func: Func,
441 ta: Apply!(<Self as Kind!( type Of<'a, T: 'a>: 'a; )>::Of<'a, A>),
442 ) -> 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>)>)
443 where
444 Func: Fn(A) -> Apply!(<F as Kind!( type Of<'a, T: 'a>: 'a; )>::Of<'a, B>) + 'a,
445 Apply!(<Self as Kind!( type Of<'a, T: 'a>: 'a; )>::Of<'a, B>): Clone,
446 {
447 match ta {
448 Some(a) => F::map(|b| Some(b), func(a)),
449 None => F::pure(None),
450 }
451 }
452 /// Sequences an option of applicative.
453 ///
454 /// This method evaluates the computation inside the option and wraps the result in the applicative context. If `None`, it returns `pure(None)`.
455 ///
456 /// ### Type Signature
457 ///
458 /// `forall f a. (Traversable Option, Applicative f) => (Option (f a)) -> f (Option a)`
459 ///
460 /// ### Type Parameters
461 ///
462 /// * `F`: The applicative context.
463 /// * `A`: The type of the elements in the traversable structure.
464 ///
465 /// ### Parameters
466 ///
467 /// * `ta`: The option containing the applicative value.
468 ///
469 /// # Returns
470 ///
471 /// The option wrapped in the applicative context.
472 ///
473 /// ### Examples
474 ///
475 /// ```
476 /// use fp_library::functions::*;
477 /// use fp_library::brands::OptionBrand;
478 ///
479 /// let x = Some(Some(5));
480 /// let y = sequence::<OptionBrand, OptionBrand, _>(x);
481 /// assert_eq!(y, Some(Some(5)));
482 /// ```
483 fn sequence<'a, F: Applicative, A: 'a + Clone>(
484 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>)>)
485 ) -> 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>)>)
486 where
487 Apply!(<F as Kind!( type Of<'a, T: 'a>: 'a; )>::Of<'a, A>): Clone,
488 Apply!(<Self as Kind!( type Of<'a, T: 'a>: 'a; )>::Of<'a, A>): Clone,
489 {
490 match ta {
491 Some(fa) => F::map(|a| Some(a), fa),
492 None => F::pure(None),
493 }
494 }
495}
496
497impl<FnBrand: SendClonableFn> ParFoldable<FnBrand> for OptionBrand {
498 /// Maps the value to a monoid and returns it, or returns empty, in parallel.
499 ///
500 /// 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.
501 ///
502 /// ### Type Signature
503 ///
504 /// `forall fn_brand m a. (ParFoldable Option, Monoid m, Send m, Sync m) => (fn_brand a m, Option a) -> m`
505 ///
506 /// ### Type Parameters
507 ///
508 /// * `M`: The monoid type (must be `Send + Sync`).
509 /// * `A`: The element type (must be `Send + Sync`).
510 ///
511 /// ### Parameters
512 ///
513 /// * `func`: The mapping function.
514 /// * `fa`: The option to fold.
515 ///
516 /// ### Returns
517 ///
518 /// The combined monoid value.
519 ///
520 /// ### Examples
521 ///
522 /// ```
523 /// use fp_library::functions::*;
524 /// use fp_library::brands::{OptionBrand, ArcFnBrand};
525 ///
526 /// let x = Some(1);
527 /// let f = send_clonable_fn_new::<ArcFnBrand, _, _>(|x: i32| x.to_string());
528 /// let y = par_fold_map::<ArcFnBrand, OptionBrand, _, _>(f, x);
529 /// assert_eq!(y, "1".to_string());
530 /// ```
531 fn par_fold_map<'a, M, A>(
532 func: <FnBrand as SendClonableFn>::SendOf<'a, A, M>,
533 fa: Apply!(<Self as Kind!( type Of<'a, T: 'a>: 'a; )>::Of<'a, A>),
534 ) -> M
535 where
536 A: 'a + Clone + Send + Sync,
537 M: Monoid + Send + Sync + 'a,
538 {
539 match fa {
540 Some(a) => func(a),
541 None => M::empty(),
542 }
543 }
544}
545
546impl Compactable for OptionBrand {
547 /// Compacts a nested option.
548 ///
549 /// This method flattens a nested option.
550 ///
551 /// ### Type Signature
552 ///
553 /// `forall a. Compactable Option => Option (Option a) -> Option a`
554 ///
555 /// ### Type Parameters
556 ///
557 /// * `A`: The type of the elements.
558 ///
559 /// ### Parameters
560 ///
561 /// * `fa`: The nested option.
562 ///
563 /// ### Returns
564 ///
565 /// The flattened option.
566 ///
567 /// ### Examples
568 ///
569 /// ```
570 /// use fp_library::functions::*;
571 /// use fp_library::brands::OptionBrand;
572 ///
573 /// let x = Some(Some(5));
574 /// let y = compact::<OptionBrand, _>(x);
575 /// assert_eq!(y, Some(5));
576 /// ```
577 fn compact<'a, A: 'a>(
578 fa: Apply!(<Self as Kind!( type Of<'a, T: 'a>: 'a; )>::Of<
579 'a,
580 Apply!(<OptionBrand as Kind!( type Of<'a, T: 'a>: 'a; )>::Of<'a, A>),
581 >)
582 ) -> Apply!(<Self as Kind!( type Of<'a, T: 'a>: 'a; )>::Of<'a, A>) {
583 fa.flatten()
584 }
585
586 /// Separates an option of result.
587 ///
588 /// This method separates an option of result into a pair of options.
589 ///
590 /// ### Type Signature
591 ///
592 /// `forall o e. Compactable Option => Option (Result o e) -> (Option o, Option e)`
593 ///
594 /// ### Type Parameters
595 ///
596 /// * `O`: The type of the success value.
597 /// * `E`: The type of the error value.
598 ///
599 /// ### Parameters
600 ///
601 /// * `fa`: The option of result.
602 ///
603 /// ### Returns
604 ///
605 /// A pair of options.
606 ///
607 /// ### Examples
608 ///
609 /// ```
610 /// use fp_library::functions::*;
611 /// use fp_library::brands::OptionBrand;
612 /// use fp_library::types::Pair;
613 ///
614 /// let x: Option<Result<i32, &str>> = Some(Ok(5));
615 /// let Pair(oks, errs) = separate::<OptionBrand, _, _>(x);
616 /// assert_eq!(oks, Some(5));
617 /// assert_eq!(errs, None);
618 /// ```
619 fn separate<'a, O: 'a, E: 'a>(
620 fa: Apply!(<Self as Kind!( type Of<'a, T: 'a>: 'a; )>::Of<'a, Result<O, E>>)
621 ) -> Pair<
622 Apply!(<Self as Kind!( type Of<'a, T: 'a>: 'a; )>::Of<'a, O>),
623 Apply!(<Self as Kind!( type Of<'a, T: 'a>: 'a; )>::Of<'a, E>),
624 > {
625 match fa {
626 Some(Ok(o)) => Pair(Some(o), None),
627 Some(Err(e)) => Pair(None, Some(e)),
628 None => Pair(None, None),
629 }
630 }
631}
632
633impl Filterable for OptionBrand {
634 /// Partitions an option based on a function that returns a result.
635 ///
636 /// This method partitions an option based on a function that returns a result.
637 ///
638 /// ### Type Signature
639 ///
640 /// `forall o e a. Filterable Option => (a -> Result o e, Option a) -> Pair (Option o) (Option e)`
641 ///
642 /// ### Type Parameters
643 ///
644 /// * `O`: The type of the success value.
645 /// * `E`: The type of the error value.
646 /// * `A`: The type of the input value.
647 /// * `Func`: The type of the function to apply.
648 ///
649 /// ### Parameters
650 ///
651 /// * `func`: The function to apply.
652 /// * `fa`: The option to partition.
653 ///
654 /// ### Returns
655 ///
656 /// A pair of options.
657 ///
658 /// ### Examples
659 ///
660 /// ```
661 /// use fp_library::functions::*;
662 /// use fp_library::brands::OptionBrand;
663 /// use fp_library::types::Pair;
664 ///
665 /// let x = Some(5);
666 /// let Pair(oks, errs) = partition_map::<OptionBrand, _, _, _, _>(|a| if a > 2 { Ok(a) } else { Err(a) }, x);
667 /// assert_eq!(oks, Some(5));
668 /// assert_eq!(errs, None);
669 /// ```
670 fn partition_map<'a, O: 'a, E: 'a, A: 'a, Func>(
671 func: Func,
672 fa: Apply!(<Self as Kind!( type Of<'a, T: 'a>: 'a; )>::Of<'a, A>),
673 ) -> Pair<
674 Apply!(<Self as Kind!( type Of<'a, T: 'a>: 'a; )>::Of<'a, O>),
675 Apply!(<Self as Kind!( type Of<'a, T: 'a>: 'a; )>::Of<'a, E>),
676 >
677 where
678 Func: Fn(A) -> Result<O, E> + 'a,
679 {
680 match fa {
681 Some(a) => match func(a) {
682 Ok(o) => Pair(Some(o), None),
683 Err(e) => Pair(None, Some(e)),
684 },
685 None => Pair(None, None),
686 }
687 }
688 /// Partitions an option based on a predicate.
689 ///
690 /// This method partitions an option based on a predicate.
691 ///
692 /// ### Type Signature
693 ///
694 /// `forall a. Filterable Option => (a -> bool, Option a) -> Pair (Option a) (Option a)`
695 ///
696 /// ### Type Parameters
697 ///
698 /// * `A`: The type of the elements.
699 /// * `Func`: The type of the predicate.
700 ///
701 /// ### Parameters
702 ///
703 /// * `func`: The predicate.
704 /// * `fa`: The option to partition.
705 ///
706 /// ### Returns
707 ///
708 /// A pair of options.
709 ///
710 /// ### Examples
711 ///
712 /// ```
713 /// use fp_library::functions::*;
714 /// use fp_library::brands::OptionBrand;
715 /// use fp_library::types::Pair;
716 ///
717 /// let x = Some(5);
718 /// let Pair(satisfied, not_satisfied) = partition::<OptionBrand, _, _>(|a| a > 2, x);
719 /// assert_eq!(satisfied, Some(5));
720 /// assert_eq!(not_satisfied, None);
721 /// ```
722 fn partition<'a, A: 'a + Clone, Func>(
723 func: Func,
724 fa: Apply!(<Self as Kind!( type Of<'a, T: 'a>: 'a; )>::Of<'a, A>),
725 ) -> Pair<
726 Apply!(<Self as Kind!( type Of<'a, T: 'a>: 'a; )>::Of<'a, A>),
727 Apply!(<Self as Kind!( type Of<'a, T: 'a>: 'a; )>::Of<'a, A>),
728 >
729 where
730 Func: Fn(A) -> bool + 'a,
731 {
732 match fa {
733 Some(a) => {
734 if func(a.clone()) {
735 Pair(Some(a), None)
736 } else {
737 Pair(None, Some(a))
738 }
739 }
740 None => Pair(None, None),
741 }
742 }
743
744 /// Maps a function over an option and filters out `None` results.
745 ///
746 /// This method maps a function over an option and filters out `None` results.
747 ///
748 /// ### Type Signature
749 ///
750 /// `forall b a. Filterable Option => (a -> Option b, Option a) -> Option b`
751 ///
752 /// ### Type Parameters
753 ///
754 /// * `B`: The type of the result of applying the function.
755 /// * `A`: The type of the input value.
756 /// * `Func`: The type of the function to apply.
757 ///
758 /// ### Parameters
759 ///
760 /// * `func`: The function to apply.
761 /// * `fa`: The option to filter and map.
762 ///
763 /// ### Returns
764 ///
765 /// The filtered and mapped option.
766 ///
767 /// ### Examples
768 ///
769 /// ```
770 /// use fp_library::functions::*;
771 /// use fp_library::brands::OptionBrand;
772 ///
773 /// let x = Some(5);
774 /// let y = filter_map::<OptionBrand, _, _, _>(|a| if a > 2 { Some(a * 2) } else { None }, x);
775 /// assert_eq!(y, Some(10));
776 /// ```
777 fn filter_map<'a, B: 'a, A: 'a, Func>(
778 func: Func,
779 fa: Apply!(<Self as Kind!( type Of<'a, T: 'a>: 'a; )>::Of<'a, A>),
780 ) -> Apply!(<Self as Kind!( type Of<'a, T: 'a>: 'a; )>::Of<'a, B>)
781 where
782 Func: Fn(A) -> Option<B> + 'a,
783 {
784 fa.and_then(func)
785 }
786
787 /// Filters an option based on a predicate.
788 ///
789 /// This method filters an option based on a predicate.
790 ///
791 /// ### Type Signature
792 ///
793 /// `forall a. Filterable Option => (a -> bool, Option a) -> Option a`
794 ///
795 /// ### Type Parameters
796 ///
797 /// * `A`: The type of the elements.
798 /// * `Func`: The type of the predicate.
799 ///
800 /// ### Parameters
801 ///
802 /// * `func`: The predicate.
803 /// * `fa`: The option to filter.
804 ///
805 /// ### Returns
806 ///
807 /// The filtered option.
808 ///
809 /// ### Examples
810 ///
811 /// ```
812 /// use fp_library::functions::*;
813 /// use fp_library::brands::OptionBrand;
814 ///
815 /// let x = Some(5);
816 /// let y = filter::<OptionBrand, _, _>(|a| a > 2, x);
817 /// assert_eq!(y, Some(5));
818 /// ```
819 fn filter<'a, A: 'a + Clone, Func>(
820 func: Func,
821 fa: Apply!(<Self as Kind!( type Of<'a, T: 'a>: 'a; )>::Of<'a, A>),
822 ) -> Apply!(<Self as Kind!( type Of<'a, T: 'a>: 'a; )>::Of<'a, A>)
823 where
824 Func: Fn(A) -> bool + 'a,
825 {
826 fa.filter(|a| func(a.clone()))
827 }
828}
829
830impl Witherable for OptionBrand {
831 /// Partitions an option based on a function that returns a result in an applicative context.
832 ///
833 /// This method partitions an option based on a function that returns a result in an applicative context.
834 ///
835 /// ### Type Signature
836 ///
837 /// `forall m o e a. (Witherable Option, Applicative m) => (a -> m (Result o e), Option a) -> m (Pair (Option o) (Option e))`
838 ///
839 /// ### Type Parameters
840 ///
841 /// * `M`: The applicative context.
842 /// * `O`: The type of the success values.
843 /// * `E`: The type of the error values.
844 /// * `A`: The type of the elements in the input structure.
845 /// * `Func`: The type of the function to apply.
846 ///
847 /// ### Parameters
848 ///
849 /// * `func`: The function to apply to each element, returning a `Result` in an applicative context.
850 /// * `ta`: The option to partition.
851 ///
852 /// ### Returns
853 ///
854 /// The partitioned option wrapped in the applicative context.
855 ///
856 /// ### Examples
857 ///
858 /// ```
859 /// use fp_library::{functions::*, brands::*, types::*};
860 ///
861 /// let x = Some(5);
862 /// let y = wilt::<OptionBrand, OptionBrand, _, _, _, _>(|a| Some(if a > 2 { Ok(a) } else { Err(a) }), x);
863 /// assert_eq!(y, Some(Pair(Some(5), None)));
864 /// ```
865 fn wilt<'a, M: Applicative, O: 'a + Clone, E: 'a + Clone, A: 'a + Clone, Func>(
866 func: Func,
867 ta: Apply!(<Self as Kind!( type Of<'a, T: 'a>: 'a; )>::Of<'a, A>),
868 ) -> Apply!(<M as Kind!( type Of<'a, T: 'a>: 'a; )>::Of<
869 'a,
870 Pair<
871 Apply!(<Self as Kind!( type Of<'a, T: 'a>: 'a; )>::Of<'a, O>),
872 Apply!(<Self as Kind!( type Of<'a, T: 'a>: 'a; )>::Of<'a, E>),
873 >,
874 >)
875 where
876 Func: Fn(A) -> Apply!(<M as Kind!( type Of<'a, T: 'a>: 'a; )>::Of<'a, Result<O, E>>) + 'a,
877 Apply!(<Self as Kind!( type Of<'a, T: 'a>: 'a; )>::Of<'a, Result<O, E>>): Clone,
878 Apply!(<M as Kind!( type Of<'a, T: 'a>: 'a; )>::Of<'a, Result<O, E>>): Clone,
879 {
880 match ta {
881 Some(a) => M::map(
882 |res| match res {
883 Ok(o) => Pair(Some(o), None),
884 Err(e) => Pair(None, Some(e)),
885 },
886 func(a),
887 ),
888 None => M::pure(Pair(None, None)),
889 }
890 }
891
892 /// Maps a function over an option and filters out `None` results in an applicative context.
893 ///
894 /// This method maps a function over an option and filters out `None` results in an applicative context.
895 ///
896 /// ### Type Signature
897 ///
898 /// `forall m b a. (Witherable Option, Applicative m) => (a -> m (Option b), Option a) -> m (Option b)`
899 ///
900 /// ### Type Parameters
901 ///
902 /// * `M`: The applicative context.
903 /// * `B`: The type of the result of applying the function.
904 /// * `A`: The type of the elements in the input structure.
905 /// * `Func`: The type of the function to apply.
906 ///
907 /// ### Parameters
908 ///
909 /// * `func`: The function to apply to each element, returning an `Option` in an applicative context.
910 /// * `ta`: The option to filter and map.
911 ///
912 /// ### Returns
913 ///
914 /// The filtered and mapped option wrapped in the applicative context.
915 ///
916 /// ### Examples
917 ///
918 /// ```
919 /// use fp_library::{functions::*, brands::*};
920 ///
921 /// let x = Some(5);
922 /// let y = wither::<OptionBrand, OptionBrand, _, _, _>(|a| Some(if a > 2 { Some(a * 2) } else { None }), x);
923 /// assert_eq!(y, Some(Some(10)));
924 /// ```
925 fn wither<'a, M: Applicative, B: 'a + Clone, A: 'a + Clone, Func>(
926 func: Func,
927 ta: Apply!(<Self as Kind!( type Of<'a, T: 'a>: 'a; )>::Of<'a, A>),
928 ) -> Apply!(<M as Kind!( type Of<'a, T: 'a>: 'a; )>::Of<
929 'a,
930 Apply!(<Self as Kind!( type Of<'a, T: 'a>: 'a; )>::Of<'a, B>),
931 >)
932 where
933 Func: Fn(A) -> Apply!(<M as Kind!( type Of<'a, T: 'a>: 'a; )>::Of<'a, Option<B>>) + 'a,
934 Apply!(<Self as Kind!( type Of<'a, T: 'a>: 'a; )>::Of<'a, Option<B>>): Clone,
935 Apply!(<M as Kind!( type Of<'a, T: 'a>: 'a; )>::Of<'a, Option<B>>): Clone,
936 {
937 match ta {
938 Some(a) => func(a),
939 None => M::pure(None),
940 }
941 }
942}
943
944#[cfg(test)]
945mod tests {
946 use super::*;
947 use crate::{brands::*, functions::*};
948 use quickcheck_macros::quickcheck;
949
950 // Functor Laws
951
952 /// Tests the identity law for Functor.
953 #[quickcheck]
954 fn functor_identity(x: Option<i32>) -> bool {
955 map::<OptionBrand, _, _, _>(identity, x) == x
956 }
957
958 /// Tests the composition law for Functor.
959 #[quickcheck]
960 fn functor_composition(x: Option<i32>) -> bool {
961 let f = |x: i32| x.wrapping_add(1);
962 let g = |x: i32| x.wrapping_mul(2);
963 map::<OptionBrand, _, _, _>(compose(f, g), x)
964 == map::<OptionBrand, _, _, _>(f, map::<OptionBrand, _, _, _>(g, x))
965 }
966
967 // Applicative Laws
968
969 /// Tests the identity law for Applicative.
970 #[quickcheck]
971 fn applicative_identity(v: Option<i32>) -> bool {
972 apply::<RcFnBrand, OptionBrand, _, _>(
973 pure::<OptionBrand, _>(<RcFnBrand as ClonableFn>::new(identity)),
974 v,
975 ) == v
976 }
977
978 /// Tests the homomorphism law for Applicative.
979 #[quickcheck]
980 fn applicative_homomorphism(x: i32) -> bool {
981 let f = |x: i32| x.wrapping_mul(2);
982 apply::<RcFnBrand, OptionBrand, _, _>(
983 pure::<OptionBrand, _>(<RcFnBrand as ClonableFn>::new(f)),
984 pure::<OptionBrand, _>(x),
985 ) == pure::<OptionBrand, _>(f(x))
986 }
987
988 /// Tests the composition law for Applicative.
989 #[quickcheck]
990 fn applicative_composition(
991 w: Option<i32>,
992 u_is_some: bool,
993 v_is_some: bool,
994 ) -> bool {
995 let v_fn = |x: i32| x.wrapping_mul(2);
996 let u_fn = |x: i32| x.wrapping_add(1);
997
998 let v = if v_is_some {
999 pure::<OptionBrand, _>(<RcFnBrand as ClonableFn>::new(v_fn))
1000 } else {
1001 None
1002 };
1003 let u = if u_is_some {
1004 pure::<OptionBrand, _>(<RcFnBrand as ClonableFn>::new(u_fn))
1005 } else {
1006 None
1007 };
1008
1009 // RHS: u <*> (v <*> w)
1010 let vw = apply::<RcFnBrand, OptionBrand, _, _>(v.clone(), w.clone());
1011 let rhs = apply::<RcFnBrand, OptionBrand, _, _>(u.clone(), vw);
1012
1013 // LHS: pure(compose) <*> u <*> v <*> w
1014 // equivalent to (u . v) <*> w
1015 let uv = match (u, v) {
1016 (Some(uf), Some(vf)) => {
1017 let composed = move |x| uf(vf(x));
1018 Some(<RcFnBrand as ClonableFn>::new(composed))
1019 }
1020 _ => None,
1021 };
1022
1023 let lhs = apply::<RcFnBrand, OptionBrand, _, _>(uv, w);
1024
1025 lhs == rhs
1026 }
1027
1028 /// Tests the interchange law for Applicative.
1029 #[quickcheck]
1030 fn applicative_interchange(y: i32) -> bool {
1031 // u <*> pure y = pure ($ y) <*> u
1032 let f = |x: i32| x.wrapping_mul(2);
1033 let u = pure::<OptionBrand, _>(<RcFnBrand as ClonableFn>::new(f));
1034
1035 let lhs = apply::<RcFnBrand, OptionBrand, _, _>(u.clone(), pure::<OptionBrand, _>(y));
1036
1037 let rhs_fn = <RcFnBrand as ClonableFn>::new(move |f: std::rc::Rc<dyn Fn(i32) -> i32>| f(y));
1038 let rhs = apply::<RcFnBrand, OptionBrand, _, _>(pure::<OptionBrand, _>(rhs_fn), u);
1039
1040 lhs == rhs
1041 }
1042
1043 // Monad Laws
1044
1045 /// Tests the left identity law for Monad.
1046 #[quickcheck]
1047 fn monad_left_identity(a: i32) -> bool {
1048 let f = |x: i32| Some(x.wrapping_mul(2));
1049 bind::<OptionBrand, _, _, _>(pure::<OptionBrand, _>(a), f) == f(a)
1050 }
1051
1052 /// Tests the right identity law for Monad.
1053 #[quickcheck]
1054 fn monad_right_identity(m: Option<i32>) -> bool {
1055 bind::<OptionBrand, _, _, _>(m, pure::<OptionBrand, _>) == m
1056 }
1057
1058 /// Tests the associativity law for Monad.
1059 #[quickcheck]
1060 fn monad_associativity(m: Option<i32>) -> bool {
1061 let f = |x: i32| Some(x.wrapping_mul(2));
1062 let g = |x: i32| Some(x.wrapping_add(1));
1063 bind::<OptionBrand, _, _, _>(bind::<OptionBrand, _, _, _>(m, f), g)
1064 == bind::<OptionBrand, _, _, _>(m, |x| bind::<OptionBrand, _, _, _>(f(x), g))
1065 }
1066
1067 // Edge Cases
1068
1069 /// Tests `map` on `None`.
1070 #[test]
1071 fn map_none() {
1072 assert_eq!(map::<OptionBrand, _, _, _>(|x: i32| x + 1, None), None);
1073 }
1074
1075 /// Tests `bind` on `None`.
1076 #[test]
1077 fn bind_none() {
1078 assert_eq!(bind::<OptionBrand, _, _, _>(None, |x: i32| Some(x + 1)), None);
1079 }
1080
1081 /// Tests `bind` returning `None`.
1082 #[test]
1083 fn bind_returning_none() {
1084 assert_eq!(bind::<OptionBrand, _, _, _>(Some(5), |_| None::<i32>), None);
1085 }
1086
1087 /// Tests `fold_right` on `None`.
1088 #[test]
1089 fn fold_right_none() {
1090 assert_eq!(
1091 crate::classes::foldable::fold_right::<RcFnBrand, OptionBrand, _, _, _>(
1092 |x: i32, acc| x + acc,
1093 0,
1094 None
1095 ),
1096 0
1097 );
1098 }
1099
1100 /// Tests `fold_left` on `None`.
1101 #[test]
1102 fn fold_left_none() {
1103 assert_eq!(
1104 crate::classes::foldable::fold_left::<RcFnBrand, OptionBrand, _, _, _>(
1105 |acc, x: i32| acc + x,
1106 0,
1107 None
1108 ),
1109 0
1110 );
1111 }
1112
1113 /// Tests `traverse` on `None`.
1114 #[test]
1115 fn traverse_none() {
1116 assert_eq!(
1117 crate::classes::traversable::traverse::<OptionBrand, OptionBrand, _, _, _>(
1118 |x: i32| Some(x + 1),
1119 None
1120 ),
1121 Some(None)
1122 );
1123 }
1124
1125 /// Tests `traverse` returning `None`.
1126 #[test]
1127 fn traverse_returning_none() {
1128 assert_eq!(
1129 crate::classes::traversable::traverse::<OptionBrand, OptionBrand, _, _, _>(
1130 |_: i32| None::<i32>,
1131 Some(5)
1132 ),
1133 None
1134 );
1135 }
1136
1137 // ParFoldable Tests
1138
1139 /// Tests `par_fold_map` on `None`.
1140 #[test]
1141 fn par_fold_map_none() {
1142 let x: Option<i32> = None;
1143 let f = send_clonable_fn_new::<ArcFnBrand, _, _>(|x: i32| x.to_string());
1144 assert_eq!(par_fold_map::<ArcFnBrand, OptionBrand, _, _>(f, x), "".to_string());
1145 }
1146
1147 /// Tests `par_fold_map` on `Some`.
1148 #[test]
1149 fn par_fold_map_some() {
1150 let x = Some(5);
1151 let f = send_clonable_fn_new::<ArcFnBrand, _, _>(|x: i32| x.to_string());
1152 assert_eq!(par_fold_map::<ArcFnBrand, OptionBrand, _, _>(f, x), "5".to_string());
1153 }
1154
1155 /// Tests `par_fold_right` on `Some`.
1156 #[test]
1157 fn par_fold_right_some() {
1158 let x = Some(5);
1159 let f = send_clonable_fn_new::<ArcFnBrand, _, _>(|(a, b): (i32, i32)| a + b);
1160 assert_eq!(par_fold_right::<ArcFnBrand, OptionBrand, _, _>(f, 10, x), 15);
1161 }
1162
1163 // Filterable Laws
1164
1165 /// Tests `filterMap identity ≡ compact`.
1166 #[quickcheck]
1167 fn filterable_filter_map_identity(x: Option<Option<i32>>) -> bool {
1168 filter_map::<OptionBrand, _, _, _>(identity, x.clone()) == compact::<OptionBrand, _>(x)
1169 }
1170
1171 /// Tests `filterMap Just ≡ identity`.
1172 #[quickcheck]
1173 fn filterable_filter_map_just(x: Option<i32>) -> bool {
1174 filter_map::<OptionBrand, _, _, _>(Some, x.clone()) == x
1175 }
1176
1177 /// Tests `filterMap (l <=< r) ≡ filterMap l <<< filterMap r`.
1178 #[quickcheck]
1179 fn filterable_filter_map_composition(x: Option<i32>) -> bool {
1180 let r = |i: i32| if i % 2 == 0 { Some(i) } else { None };
1181 let l = |i: i32| if i > 5 { Some(i) } else { None };
1182 let composed = |i| r(i).and_then(l);
1183
1184 filter_map::<OptionBrand, _, _, _>(composed, x.clone())
1185 == filter_map::<OptionBrand, _, _, _>(l, filter_map::<OptionBrand, _, _, _>(r, x))
1186 }
1187
1188 /// Tests `filter ≡ filterMap <<< maybeBool`.
1189 #[quickcheck]
1190 fn filterable_filter_consistency(x: Option<i32>) -> bool {
1191 let p = |i: i32| i % 2 == 0;
1192 let maybe_bool = |i| if p(i) { Some(i) } else { None };
1193
1194 filter::<OptionBrand, _, _>(p, x.clone())
1195 == filter_map::<OptionBrand, _, _, _>(maybe_bool, x)
1196 }
1197
1198 /// Tests `partitionMap identity ≡ separate`.
1199 #[quickcheck]
1200 fn filterable_partition_map_identity(x: Option<Result<i32, i32>>) -> bool {
1201 partition_map::<OptionBrand, _, _, _, _>(identity, x.clone())
1202 == separate::<OptionBrand, _, _>(x)
1203 }
1204
1205 /// Tests `partitionMap Right ≡ identity` (on the right side).
1206 #[quickcheck]
1207 fn filterable_partition_map_right_identity(x: Option<i32>) -> bool {
1208 let Pair(oks, _) = partition_map::<OptionBrand, _, _, _, _>(Ok::<_, i32>, x.clone());
1209 oks == x
1210 }
1211
1212 /// Tests `partitionMap Left ≡ identity` (on the left side).
1213 #[quickcheck]
1214 fn filterable_partition_map_left_identity(x: Option<i32>) -> bool {
1215 let Pair(_, errs) = partition_map::<OptionBrand, _, _, _, _>(Err::<i32, _>, x.clone());
1216 errs == x
1217 }
1218
1219 /// Tests `f <<< partition ≡ partitionMap <<< eitherBool`.
1220 #[quickcheck]
1221 fn filterable_partition_consistency(x: Option<i32>) -> bool {
1222 let p = |i: i32| i % 2 == 0;
1223 let either_bool = |i| if p(i) { Ok(i) } else { Err(i) };
1224
1225 let Pair(satisfied, not_satisfied) = partition::<OptionBrand, _, _>(p, x.clone());
1226 let Pair(oks, errs) = partition_map::<OptionBrand, _, _, _, _>(either_bool, x);
1227
1228 satisfied == oks && not_satisfied == errs
1229 }
1230
1231 // Witherable Laws
1232
1233 /// Tests `wither (pure <<< Just) ≡ pure`.
1234 #[quickcheck]
1235 fn witherable_identity(x: Option<i32>) -> bool {
1236 wither::<OptionBrand, OptionBrand, _, _, _>(|i| Some(Some(i)), x.clone()) == Some(x)
1237 }
1238
1239 /// Tests `wilt p ≡ map separate <<< traverse p`.
1240 #[quickcheck]
1241 fn witherable_wilt_consistency(x: Option<i32>) -> bool {
1242 let p = |i: i32| Some(if i % 2 == 0 { Ok(i) } else { Err(i) });
1243
1244 let lhs = wilt::<OptionBrand, OptionBrand, _, _, _, _>(p, x.clone());
1245 let rhs = map::<OptionBrand, _, _, _>(
1246 |res| separate::<OptionBrand, _, _>(res),
1247 traverse::<OptionBrand, OptionBrand, _, _, _>(p, x),
1248 );
1249
1250 lhs == rhs
1251 }
1252
1253 /// Tests `wither p ≡ map compact <<< traverse p`.
1254 #[quickcheck]
1255 fn witherable_wither_consistency(x: Option<i32>) -> bool {
1256 let p = |i: i32| Some(if i % 2 == 0 { Some(i) } else { None });
1257
1258 let lhs = wither::<OptionBrand, OptionBrand, _, _, _>(p, x.clone());
1259 let rhs = map::<OptionBrand, _, _, _>(
1260 |opt| compact::<OptionBrand, _>(opt),
1261 traverse::<OptionBrand, OptionBrand, _, _, _>(p, x),
1262 );
1263
1264 lhs == rhs
1265 }
1266
1267 // Edge Cases
1268
1269 /// Tests `compact` on `Some(None)`.
1270 #[test]
1271 fn compact_some_none() {
1272 assert_eq!(compact::<OptionBrand, _>(Some(None::<i32>)), None);
1273 }
1274
1275 /// Tests `compact` on `Some(Some(x))`.
1276 #[test]
1277 fn compact_some_some() {
1278 assert_eq!(compact::<OptionBrand, _>(Some(Some(5))), Some(5));
1279 }
1280
1281 /// Tests `compact` on `None`.
1282 #[test]
1283 fn compact_none() {
1284 assert_eq!(compact::<OptionBrand, _>(None::<Option<i32>>), None);
1285 }
1286
1287 /// Tests `separate` on `Some(Ok(x))`.
1288 #[test]
1289 fn separate_some_ok() {
1290 let Pair(oks, errs) = separate::<OptionBrand, _, _>(Some(Ok::<i32, &str>(5)));
1291 assert_eq!(oks, Some(5));
1292 assert_eq!(errs, None);
1293 }
1294
1295 /// Tests `separate` on `Some(Err(e))`.
1296 #[test]
1297 fn separate_some_err() {
1298 let Pair(oks, errs) = separate::<OptionBrand, _, _>(Some(Err::<i32, &str>("error")));
1299 assert_eq!(oks, None);
1300 assert_eq!(errs, Some("error"));
1301 }
1302
1303 /// Tests `separate` on `None`.
1304 #[test]
1305 fn separate_none() {
1306 let Pair(oks, errs) = separate::<OptionBrand, _, _>(None::<Result<i32, &str>>);
1307 assert_eq!(oks, None);
1308 assert_eq!(errs, None);
1309 }
1310
1311 /// Tests `partition_map` on `None`.
1312 #[test]
1313 fn partition_map_none() {
1314 let Pair(oks, errs) =
1315 partition_map::<OptionBrand, _, _, _, _>(|x: i32| Ok::<i32, i32>(x), None::<i32>);
1316 assert_eq!(oks, None);
1317 assert_eq!(errs, None);
1318 }
1319
1320 /// Tests `partition` on `None`.
1321 #[test]
1322 fn partition_none() {
1323 let Pair(satisfied, not_satisfied) =
1324 partition::<OptionBrand, _, _>(|x: i32| x > 0, None::<i32>);
1325 assert_eq!(satisfied, None);
1326 assert_eq!(not_satisfied, None);
1327 }
1328
1329 /// Tests `filter_map` on `None`.
1330 #[test]
1331 fn filter_map_none() {
1332 assert_eq!(filter_map::<OptionBrand, _, _, _>(|x: i32| Some(x), None::<i32>), None);
1333 }
1334
1335 /// Tests `filter` on `None`.
1336 #[test]
1337 fn filter_none() {
1338 assert_eq!(filter::<OptionBrand, _, _>(|x: i32| x > 0, None::<i32>), None);
1339 }
1340
1341 /// Tests `wilt` on `None`.
1342 #[test]
1343 fn wilt_none() {
1344 let res = wilt::<OptionBrand, OptionBrand, _, _, _, _>(
1345 |x: i32| Some(Ok::<i32, i32>(x)),
1346 None::<i32>,
1347 );
1348 assert_eq!(res, Some(Pair(None, None)));
1349 }
1350
1351 /// Tests `wither` on `None`.
1352 #[test]
1353 fn wither_none() {
1354 let res = wither::<OptionBrand, OptionBrand, _, _, _>(|x: i32| Some(Some(x)), None::<i32>);
1355 assert_eq!(res, Some(None));
1356 }
1357}