fp_library/types/result.rs
1//! Implementations for [`Result`].
2
3use crate::{
4 brands::{ResultBrand, ResultWithErrBrand, ResultWithOkBrand},
5 classes::{
6 applicative::Applicative,
7 apply_first::ApplyFirst,
8 apply_second::ApplySecond,
9 clonable_fn::{ApplyClonableFn, ClonableFn},
10 foldable::Foldable,
11 functor::Functor,
12 lift::Lift,
13 monoid::Monoid,
14 pointed::Pointed,
15 semiapplicative::Semiapplicative,
16 semimonad::Semimonad,
17 traversable::Traversable,
18 },
19 hkt::{Apply1L1T, Kind0L2T, Kind1L1T},
20};
21
22impl Kind0L2T for ResultBrand {
23 type Output<A, B> = Result<B, A>;
24}
25
26// ResultWithErrBrand<E> (Functor over T)
27
28impl<E: 'static> Kind1L1T for ResultWithErrBrand<E> {
29 type Output<'a, A: 'a> = Result<A, E>;
30}
31
32impl<E: 'static> Functor for ResultWithErrBrand<E> {
33 /// Maps a function over the value in the result.
34 ///
35 /// # Type Signature
36 ///
37 /// `forall a b e. Functor (Result e) => (a -> b, Result e a) -> Result e b`
38 ///
39 /// # Parameters
40 ///
41 /// * `f`: The function to apply.
42 /// * `fa`: The result to map over.
43 ///
44 /// # Returns
45 ///
46 /// A new result containing the result of applying the function, or the original error.
47 ///
48 /// # Examples
49 ///
50 /// ```
51 /// use fp_library::classes::functor::map;
52 /// use fp_library::brands::ResultWithErrBrand;
53 ///
54 /// assert_eq!(map::<ResultWithErrBrand<()>, _, _, _>(|x: i32| x * 2, Ok(5)), Ok(10));
55 /// assert_eq!(map::<ResultWithErrBrand<i32>, _, _, _>(|x: i32| x * 2, Err(1)), Err(1));
56 /// ```
57 fn map<'a, A: 'a, B: 'a, F>(
58 f: F,
59 fa: Apply1L1T<'a, Self, A>,
60 ) -> Apply1L1T<'a, Self, B>
61 where
62 F: Fn(A) -> B + 'a,
63 {
64 fa.map(f)
65 }
66}
67
68impl<E: Clone + 'static> Lift for ResultWithErrBrand<E> {
69 /// Lifts a binary function into the result context.
70 ///
71 /// # Type Signature
72 ///
73 /// `forall a b c e. Lift (Result e) => ((a, b) -> c, Result e a, Result e b) -> Result e c`
74 ///
75 /// # Parameters
76 ///
77 /// * `f`: The binary function to apply.
78 /// * `fa`: The first result.
79 /// * `fb`: The second result.
80 ///
81 /// # Returns
82 ///
83 /// `Ok(f(a, b))` if both results are `Ok`, otherwise the first error encountered.
84 ///
85 /// # Examples
86 ///
87 /// ```
88 /// use fp_library::classes::lift::lift2;
89 /// use fp_library::brands::ResultWithErrBrand;
90 ///
91 /// assert_eq!(
92 /// lift2::<ResultWithErrBrand<()>, _, _, _, _>(|x: i32, y: i32| x + y, Ok(1), Ok(2)),
93 /// Ok(3)
94 /// );
95 /// assert_eq!(
96 /// lift2::<ResultWithErrBrand<i32>, _, _, _, _>(|x: i32, y: i32| x + y, Ok(1), Err(2)),
97 /// Err(2)
98 /// );
99 /// ```
100 fn lift2<'a, A, B, C, F>(
101 f: F,
102 fa: Apply1L1T<'a, Self, A>,
103 fb: Apply1L1T<'a, Self, B>,
104 ) -> Apply1L1T<'a, Self, C>
105 where
106 F: Fn(A, B) -> C + 'a,
107 A: Clone + 'a,
108 B: Clone + 'a,
109 C: 'a,
110 {
111 match (fa, fb) {
112 (Ok(a), Ok(b)) => Ok(f(a, b)),
113 (Err(e), _) => Err(e),
114 (_, Err(e)) => Err(e),
115 }
116 }
117}
118
119impl<E: 'static> Pointed for ResultWithErrBrand<E> {
120 /// Wraps a value in a result.
121 ///
122 /// # Type Signature
123 ///
124 /// `forall a e. Pointed (Result e) => a -> Result e a`
125 ///
126 /// # Parameters
127 ///
128 /// * `a`: The value to wrap.
129 ///
130 /// # Returns
131 ///
132 /// `Ok(a)`.
133 ///
134 /// # Examples
135 ///
136 /// ```
137 /// use fp_library::classes::pointed::pure;
138 /// use fp_library::brands::ResultWithErrBrand;
139 ///
140 /// assert_eq!(pure::<ResultWithErrBrand<()>, _>(5), Ok(5));
141 /// ```
142 fn pure<'a, A: 'a>(a: A) -> Apply1L1T<'a, Self, A> {
143 Ok(a)
144 }
145}
146
147impl<E: Clone + 'static> ApplyFirst for ResultWithErrBrand<E> {}
148impl<E: Clone + 'static> ApplySecond for ResultWithErrBrand<E> {}
149
150impl<E: Clone + 'static> Semiapplicative for ResultWithErrBrand<E> {
151 /// Applies a wrapped function to a wrapped value.
152 ///
153 /// # Type Signature
154 ///
155 /// `forall a b e. Semiapplicative (Result e) => (Result e (a -> b), Result e a) -> Result e b`
156 ///
157 /// # Parameters
158 ///
159 /// * `ff`: The result containing the function.
160 /// * `fa`: The result containing the value.
161 ///
162 /// # Returns
163 ///
164 /// `Ok(f(a))` if both are `Ok`, otherwise the first error encountered.
165 ///
166 /// # Examples
167 ///
168 /// ```
169 /// use fp_library::classes::semiapplicative::apply;
170 /// use fp_library::classes::clonable_fn::ClonableFn;
171 /// use fp_library::brands::ResultWithErrBrand;
172 /// use fp_library::brands::RcFnBrand;
173 /// use std::rc::Rc;
174 ///
175 /// let f = Ok(<RcFnBrand as ClonableFn>::new(|x: i32| x * 2));
176 /// assert_eq!(apply::<ResultWithErrBrand<()>, _, _, RcFnBrand>(f, Ok(5)), Ok(10));
177 /// ```
178 fn apply<'a, A: 'a + Clone, B: 'a, FnBrand: 'a + ClonableFn>(
179 ff: Apply1L1T<'a, Self, ApplyClonableFn<'a, FnBrand, A, B>>,
180 fa: Apply1L1T<'a, Self, A>,
181 ) -> Apply1L1T<'a, Self, B> {
182 match (ff, fa) {
183 (Ok(f), Ok(a)) => Ok(f(a)),
184 (Err(e), _) => Err(e),
185 (_, Err(e)) => Err(e),
186 }
187 }
188}
189
190impl<E: Clone + 'static> Semimonad for ResultWithErrBrand<E> {
191 /// Chains result computations.
192 ///
193 /// # Type Signature
194 ///
195 /// `forall a b e. Semimonad (Result e) => (Result e a, a -> Result e b) -> Result e b`
196 ///
197 /// # Parameters
198 ///
199 /// * `ma`: The first result.
200 /// * `f`: The function to apply to the value inside the result.
201 ///
202 /// # Returns
203 ///
204 /// The result of applying `f` to the value if `ma` is `Ok`, otherwise the original error.
205 ///
206 /// # Examples
207 ///
208 /// ```
209 /// use fp_library::classes::semimonad::bind;
210 /// use fp_library::brands::ResultWithErrBrand;
211 ///
212 /// assert_eq!(
213 /// bind::<ResultWithErrBrand<()>, _, _, _>(Ok(5), |x| Ok(x * 2)),
214 /// Ok(10)
215 /// );
216 /// ```
217 fn bind<'a, A: 'a, B: 'a, F>(
218 ma: Apply1L1T<'a, Self, A>,
219 f: F,
220 ) -> Apply1L1T<'a, Self, B>
221 where
222 F: Fn(A) -> Apply1L1T<'a, Self, B> + 'a,
223 {
224 ma.and_then(f)
225 }
226}
227
228impl<E: 'static> Foldable for ResultWithErrBrand<E> {
229 /// Folds the result from the right.
230 ///
231 /// # Type Signature
232 ///
233 /// `forall a b e. Foldable (Result e) => ((a, b) -> b, b, Result e a) -> b`
234 ///
235 /// # Parameters
236 ///
237 /// * `f`: The folding function.
238 /// * `init`: The initial value.
239 /// * `fa`: The result to fold.
240 ///
241 /// # Returns
242 ///
243 /// `f(a, init)` if `fa` is `Ok(a)`, otherwise `init`.
244 ///
245 /// # Examples
246 ///
247 /// ```
248 /// use fp_library::classes::foldable::fold_right;
249 /// use fp_library::brands::ResultWithErrBrand;
250 ///
251 /// assert_eq!(fold_right::<ResultWithErrBrand<()>, _, _, _>(|x, acc| x + acc, 0, Ok(5)), 5);
252 /// assert_eq!(fold_right::<ResultWithErrBrand<i32>, _, _, _>(|x: i32, acc| x + acc, 0, Err(1)), 0);
253 /// ```
254 fn fold_right<'a, A: 'a, B: 'a, F>(
255 f: F,
256 init: B,
257 fa: Apply1L1T<'a, Self, A>,
258 ) -> B
259 where
260 F: Fn(A, B) -> B + 'a,
261 {
262 match fa {
263 Ok(a) => f(a, init),
264 Err(_) => init,
265 }
266 }
267
268 /// Folds the result from the left.
269 ///
270 /// # Type Signature
271 ///
272 /// `forall a b e. Foldable (Result e) => ((b, a) -> b, b, Result e a) -> b`
273 ///
274 /// # Parameters
275 ///
276 /// * `f`: The folding function.
277 /// * `init`: The initial value.
278 /// * `fa`: The result to fold.
279 ///
280 /// # Returns
281 ///
282 /// `f(init, a)` if `fa` is `Ok(a)`, otherwise `init`.
283 ///
284 /// # Examples
285 ///
286 /// ```
287 /// use fp_library::classes::foldable::fold_left;
288 /// use fp_library::brands::ResultWithErrBrand;
289 ///
290 /// assert_eq!(fold_left::<ResultWithErrBrand<()>, _, _, _>(|acc, x| acc + x, 0, Ok(5)), 5);
291 /// ```
292 fn fold_left<'a, A: 'a, B: 'a, F>(
293 f: F,
294 init: B,
295 fa: Apply1L1T<'a, Self, A>,
296 ) -> B
297 where
298 F: Fn(B, A) -> B + 'a,
299 {
300 match fa {
301 Ok(a) => f(init, a),
302 Err(_) => init,
303 }
304 }
305
306 /// Maps the value to a monoid and returns it.
307 ///
308 /// # Type Signature
309 ///
310 /// `forall a m e. (Foldable (Result e), Monoid m) => ((a) -> m, Result e a) -> m`
311 ///
312 /// # Parameters
313 ///
314 /// * `f`: The mapping function.
315 /// * `fa`: The result to fold.
316 ///
317 /// # Returns
318 ///
319 /// `f(a)` if `fa` is `Ok(a)`, otherwise `M::empty()`.
320 ///
321 /// # Examples
322 ///
323 /// ```
324 /// use fp_library::classes::foldable::fold_map;
325 /// use fp_library::brands::ResultWithErrBrand;
326 /// use fp_library::types::string;
327 ///
328 /// assert_eq!(
329 /// fold_map::<ResultWithErrBrand<()>, _, _, _>(|x: i32| x.to_string(), Ok(5)),
330 /// "5".to_string()
331 /// );
332 /// ```
333 fn fold_map<'a, A: 'a, M, F>(
334 f: F,
335 fa: Apply1L1T<'a, Self, A>,
336 ) -> M
337 where
338 M: Monoid + 'a,
339 F: Fn(A) -> M + 'a,
340 {
341 match fa {
342 Ok(a) => f(a),
343 Err(_) => M::empty(),
344 }
345 }
346}
347
348impl<E: Clone + 'static> Traversable for ResultWithErrBrand<E> {
349 /// Traverses the result with an applicative function.
350 ///
351 /// # Type Signature
352 ///
353 /// `forall a b f e. (Traversable (Result e), Applicative f) => (a -> f b, Result e a) -> f (Result e b)`
354 ///
355 /// # Parameters
356 ///
357 /// * `f`: The function to apply.
358 /// * `ta`: The result to traverse.
359 ///
360 /// # Returns
361 ///
362 /// The result wrapped in the applicative context.
363 ///
364 /// # Examples
365 ///
366 /// ```
367 /// use fp_library::classes::traversable::traverse;
368 /// use fp_library::brands::{ResultWithErrBrand, OptionBrand};
369 ///
370 /// assert_eq!(
371 /// traverse::<ResultWithErrBrand<()>, OptionBrand, _, _, _>(|x| Some(x * 2), Ok(5)),
372 /// Some(Ok(10))
373 /// );
374 /// ```
375 fn traverse<'a, F: Applicative, A: 'a + Clone, B: 'a + Clone, Func>(
376 f: Func,
377 ta: Apply1L1T<'a, Self, A>,
378 ) -> Apply1L1T<'a, F, Apply1L1T<'a, Self, B>>
379 where
380 Func: Fn(A) -> Apply1L1T<'a, F, B> + 'a,
381 Apply1L1T<'a, Self, B>: Clone,
382 {
383 match ta {
384 Ok(a) => F::map(|b| Ok(b), f(a)),
385 Err(e) => F::pure(Err(e)),
386 }
387 }
388
389 /// Sequences a result of applicative.
390 ///
391 /// # Type Signature
392 ///
393 /// `forall a f e. (Traversable (Result e), Applicative f) => (Result e (f a)) -> f (Result e a)`
394 ///
395 /// # Parameters
396 ///
397 /// * `ta`: The result containing the applicative value.
398 ///
399 /// # Returns
400 ///
401 /// The result wrapped in the applicative context.
402 ///
403 /// # Examples
404 ///
405 /// ```
406 /// use fp_library::classes::traversable::sequence;
407 /// use fp_library::brands::{ResultWithErrBrand, OptionBrand};
408 ///
409 /// assert_eq!(
410 /// sequence::<ResultWithErrBrand<()>, OptionBrand, _>(Ok(Some(5))),
411 /// Some(Ok(5))
412 /// );
413 /// ```
414 fn sequence<'a, F: Applicative, A: 'a + Clone>(
415 ta: Apply1L1T<'a, Self, Apply1L1T<'a, F, A>>
416 ) -> Apply1L1T<'a, F, Apply1L1T<'a, Self, A>>
417 where
418 Apply1L1T<'a, F, A>: Clone,
419 Apply1L1T<'a, Self, A>: Clone,
420 {
421 match ta {
422 Ok(fa) => F::map(|a| Ok(a), fa),
423 Err(e) => F::pure(Err(e)),
424 }
425 }
426}
427
428// ResultWithOkBrand<T> (Functor over E)
429
430impl<T: 'static> Kind1L1T for ResultWithOkBrand<T> {
431 type Output<'a, A: 'a> = Result<T, A>;
432}
433
434impl<T: 'static> Functor for ResultWithOkBrand<T> {
435 /// Maps a function over the error value in the result.
436 ///
437 /// # Type Signature
438 ///
439 /// `forall a b t. Functor (Result' t) => (a -> b, Result t a) -> Result t b`
440 ///
441 /// # Parameters
442 ///
443 /// * `f`: The function to apply to the error.
444 /// * `fa`: The result to map over.
445 ///
446 /// # Returns
447 ///
448 /// A new result containing the mapped error, or the original success value.
449 ///
450 /// # Examples
451 ///
452 /// ```
453 /// use fp_library::classes::functor::map;
454 /// use fp_library::brands::ResultWithOkBrand;
455 ///
456 /// assert_eq!(map::<ResultWithOkBrand<i32>, _, _, _>(|x: i32| x * 2, Err(5)), Err(10));
457 /// assert_eq!(map::<ResultWithOkBrand<i32>, _, _, _>(|x: i32| x * 2, Ok(1)), Ok(1));
458 /// ```
459 fn map<'a, A: 'a, B: 'a, F>(
460 f: F,
461 fa: Apply1L1T<'a, Self, A>,
462 ) -> Apply1L1T<'a, Self, B>
463 where
464 F: Fn(A) -> B + 'a,
465 {
466 match fa {
467 Ok(t) => Ok(t),
468 Err(e) => Err(f(e)),
469 }
470 }
471}
472
473impl<T: Clone + 'static> Lift for ResultWithOkBrand<T> {
474 /// Lifts a binary function into the result context (over error).
475 ///
476 /// # Type Signature
477 ///
478 /// `forall a b c t. Lift (Result' t) => ((a, b) -> c, Result t a, Result t b) -> Result t c`
479 ///
480 /// # Parameters
481 ///
482 /// * `f`: The binary function to apply to the errors.
483 /// * `fa`: The first result.
484 /// * `fb`: The second result.
485 ///
486 /// # Returns
487 ///
488 /// `Err(f(a, b))` if both results are `Err`, otherwise the first success encountered.
489 ///
490 /// # Examples
491 ///
492 /// ```
493 /// use fp_library::classes::lift::lift2;
494 /// use fp_library::brands::ResultWithOkBrand;
495 ///
496 /// assert_eq!(
497 /// lift2::<ResultWithOkBrand<i32>, _, _, _, _>(|x: i32, y: i32| x + y, Err(1), Err(2)),
498 /// Err(3)
499 /// );
500 /// ```
501 fn lift2<'a, A, B, C, F>(
502 f: F,
503 fa: Apply1L1T<'a, Self, A>,
504 fb: Apply1L1T<'a, Self, B>,
505 ) -> Apply1L1T<'a, Self, C>
506 where
507 F: Fn(A, B) -> C + 'a,
508 A: Clone + 'a,
509 B: Clone + 'a,
510 C: 'a,
511 {
512 match (fa, fb) {
513 (Err(a), Err(b)) => Err(f(a, b)),
514 (Ok(t), _) => Ok(t),
515 (_, Ok(t)) => Ok(t),
516 }
517 }
518}
519
520impl<T: 'static> Pointed for ResultWithOkBrand<T> {
521 /// Wraps a value in a result (as error).
522 ///
523 /// # Type Signature
524 ///
525 /// `forall a t. Pointed (Result' t) => a -> Result t a`
526 ///
527 /// # Parameters
528 ///
529 /// * `a`: The value to wrap.
530 ///
531 /// # Returns
532 ///
533 /// `Err(a)`.
534 ///
535 /// # Examples
536 ///
537 /// ```
538 /// use fp_library::classes::pointed::pure;
539 /// use fp_library::brands::ResultWithOkBrand;
540 ///
541 /// assert_eq!(pure::<ResultWithOkBrand<()>, _>(5), Err(5));
542 /// ```
543 fn pure<'a, A: 'a>(a: A) -> Apply1L1T<'a, Self, A> {
544 Err(a)
545 }
546}
547
548impl<T: Clone + 'static> ApplyFirst for ResultWithOkBrand<T> {}
549impl<T: Clone + 'static> ApplySecond for ResultWithOkBrand<T> {}
550
551impl<T: Clone + 'static> Semiapplicative for ResultWithOkBrand<T> {
552 /// Applies a wrapped function to a wrapped value (over error).
553 ///
554 /// # Type Signature
555 ///
556 /// `forall a b t. Semiapplicative (Result' t) => (Result t (a -> b), Result t a) -> Result t b`
557 ///
558 /// # Parameters
559 ///
560 /// * `ff`: The result containing the function (in Err).
561 /// * `fa`: The result containing the value (in Err).
562 ///
563 /// # Returns
564 ///
565 /// `Err(f(a))` if both are `Err`, otherwise the first success encountered.
566 ///
567 /// # Examples
568 ///
569 /// ```
570 /// use fp_library::classes::semiapplicative::apply;
571 /// use fp_library::classes::clonable_fn::ClonableFn;
572 /// use fp_library::brands::ResultWithOkBrand;
573 /// use fp_library::brands::RcFnBrand;
574 /// use std::rc::Rc;
575 ///
576 /// let f = Err(<RcFnBrand as ClonableFn>::new(|x: i32| x * 2));
577 /// assert_eq!(apply::<ResultWithOkBrand<()>, _, _, RcFnBrand>(f, Err(5)), Err(10));
578 /// ```
579 fn apply<'a, A: 'a + Clone, B: 'a, FnBrand: 'a + ClonableFn>(
580 ff: Apply1L1T<'a, Self, ApplyClonableFn<'a, FnBrand, A, B>>,
581 fa: Apply1L1T<'a, Self, A>,
582 ) -> Apply1L1T<'a, Self, B> {
583 match (ff, fa) {
584 (Err(f), Err(a)) => Err(f(a)),
585 (Ok(t), _) => Ok(t),
586 (_, Ok(t)) => Ok(t),
587 }
588 }
589}
590
591impl<T: Clone + 'static> Semimonad for ResultWithOkBrand<T> {
592 /// Chains result computations (over error).
593 ///
594 /// # Type Signature
595 ///
596 /// `forall a b t. Semimonad (Result' t) => (Result t a, a -> Result t b) -> Result t b`
597 ///
598 /// # Parameters
599 ///
600 /// * `ma`: The first result.
601 /// * `f`: The function to apply to the error value.
602 ///
603 /// # Returns
604 ///
605 /// The result of applying `f` to the error if `ma` is `Err`, otherwise the original success.
606 ///
607 /// # Examples
608 ///
609 /// ```
610 /// use fp_library::classes::semimonad::bind;
611 /// use fp_library::brands::ResultWithOkBrand;
612 ///
613 /// assert_eq!(
614 /// bind::<ResultWithOkBrand<()>, _, _, _>(Err(5), |x| Err(x * 2)),
615 /// Err(10)
616 /// );
617 /// ```
618 fn bind<'a, A: 'a, B: 'a, F>(
619 ma: Apply1L1T<'a, Self, A>,
620 f: F,
621 ) -> Apply1L1T<'a, Self, B>
622 where
623 F: Fn(A) -> Apply1L1T<'a, Self, B> + 'a,
624 {
625 match ma {
626 Ok(t) => Ok(t),
627 Err(e) => f(e),
628 }
629 }
630}
631
632impl<T: 'static> Foldable for ResultWithOkBrand<T> {
633 /// Folds the result from the right (over error).
634 ///
635 /// # Type Signature
636 ///
637 /// `forall a b t. Foldable (Result' t) => ((a, b) -> b, b, Result t a) -> b`
638 ///
639 /// # Parameters
640 ///
641 /// * `f`: The folding function.
642 /// * `init`: The initial value.
643 /// * `fa`: The result to fold.
644 ///
645 /// # Returns
646 ///
647 /// `f(a, init)` if `fa` is `Err(a)`, otherwise `init`.
648 ///
649 /// # Examples
650 ///
651 /// ```
652 /// use fp_library::classes::foldable::fold_right;
653 /// use fp_library::brands::ResultWithOkBrand;
654 ///
655 /// assert_eq!(fold_right::<ResultWithOkBrand<i32>, _, _, _>(|x: i32, acc| x + acc, 0, Err(1)), 1);
656 /// assert_eq!(fold_right::<ResultWithOkBrand<()>, _, _, _>(|x: i32, acc| x + acc, 0, Ok(())), 0);
657 /// ```
658 fn fold_right<'a, A: 'a, B: 'a, F>(
659 f: F,
660 init: B,
661 fa: Apply1L1T<'a, Self, A>,
662 ) -> B
663 where
664 F: Fn(A, B) -> B + 'a,
665 {
666 match fa {
667 Err(e) => f(e, init),
668 Ok(_) => init,
669 }
670 }
671
672 /// Folds the result from the left (over error).
673 ///
674 /// # Type Signature
675 ///
676 /// `forall a b t. Foldable (Result' t) => ((b, a) -> b, b, Result t a) -> b`
677 ///
678 /// # Parameters
679 ///
680 /// * `f`: The folding function.
681 /// * `init`: The initial value.
682 /// * `fa`: The result to fold.
683 ///
684 /// # Returns
685 ///
686 /// `f(init, a)` if `fa` is `Err(a)`, otherwise `init`.
687 ///
688 /// # Examples
689 ///
690 /// ```
691 /// use fp_library::classes::foldable::fold_left;
692 /// use fp_library::brands::ResultWithOkBrand;
693 ///
694 /// assert_eq!(fold_left::<ResultWithOkBrand<()>, _, _, _>(|acc, x| acc + x, 0, Err(5)), 5);
695 /// ```
696 fn fold_left<'a, A: 'a, B: 'a, F>(
697 f: F,
698 init: B,
699 fa: Apply1L1T<'a, Self, A>,
700 ) -> B
701 where
702 F: Fn(B, A) -> B + 'a,
703 {
704 match fa {
705 Err(e) => f(init, e),
706 Ok(_) => init,
707 }
708 }
709
710 /// Maps the value to a monoid and returns it (over error).
711 ///
712 /// # Type Signature
713 ///
714 /// `forall a m t. (Foldable (Result' t), Monoid m) => ((a) -> m, Result t a) -> m`
715 ///
716 /// # Parameters
717 ///
718 /// * `f`: The mapping function.
719 /// * `fa`: The result to fold.
720 ///
721 /// # Returns
722 ///
723 /// `f(a)` if `fa` is `Err(a)`, otherwise `M::empty()`.
724 ///
725 /// # Examples
726 ///
727 /// ```
728 /// use fp_library::classes::foldable::fold_map;
729 /// use fp_library::brands::ResultWithOkBrand;
730 /// use fp_library::types::string;
731 ///
732 /// assert_eq!(
733 /// fold_map::<ResultWithOkBrand<()>, _, _, _>(|x: i32| x.to_string(), Err(5)),
734 /// "5".to_string()
735 /// );
736 /// ```
737 fn fold_map<'a, A: 'a, M, F>(
738 f: F,
739 fa: Apply1L1T<'a, Self, A>,
740 ) -> M
741 where
742 M: Monoid + 'a,
743 F: Fn(A) -> M + 'a,
744 {
745 match fa {
746 Err(e) => f(e),
747 Ok(_) => M::empty(),
748 }
749 }
750}
751
752impl<T: Clone + 'static> Traversable for ResultWithOkBrand<T> {
753 /// Traverses the result with an applicative function (over error).
754 ///
755 /// # Type Signature
756 ///
757 /// `forall a b f t. (Traversable (Result' t), Applicative f) => (a -> f b, Result t a) -> f (Result t b)`
758 ///
759 /// # Parameters
760 ///
761 /// * `f`: The function to apply.
762 /// * `ta`: The result to traverse.
763 ///
764 /// # Returns
765 ///
766 /// The result wrapped in the applicative context.
767 ///
768 /// # Examples
769 ///
770 /// ```
771 /// use fp_library::classes::traversable::traverse;
772 /// use fp_library::brands::{ResultWithOkBrand, OptionBrand};
773 ///
774 /// assert_eq!(
775 /// traverse::<ResultWithOkBrand<()>, OptionBrand, _, _, _>(|x| Some(x * 2), Err(5)),
776 /// Some(Err(10))
777 /// );
778 /// ```
779 fn traverse<'a, F: Applicative, A: 'a + Clone, B: 'a + Clone, Func>(
780 f: Func,
781 ta: Apply1L1T<'a, Self, A>,
782 ) -> Apply1L1T<'a, F, Apply1L1T<'a, Self, B>>
783 where
784 Func: Fn(A) -> Apply1L1T<'a, F, B> + 'a,
785 Apply1L1T<'a, Self, B>: Clone,
786 {
787 match ta {
788 Err(e) => F::map(|b| Err(b), f(e)),
789 Ok(t) => F::pure(Ok(t)),
790 }
791 }
792
793 /// Sequences a result of applicative (over error).
794 ///
795 /// # Type Signature
796 ///
797 /// `forall a f t. (Traversable (Result' t), Applicative f) => (Result t (f a)) -> f (Result t a)`
798 ///
799 /// # Parameters
800 ///
801 /// * `ta`: The result containing the applicative value.
802 ///
803 /// # Returns
804 ///
805 /// The result wrapped in the applicative context.
806 ///
807 /// # Examples
808 ///
809 /// ```
810 /// use fp_library::classes::traversable::sequence;
811 /// use fp_library::brands::{ResultWithOkBrand, OptionBrand};
812 ///
813 /// assert_eq!(
814 /// sequence::<ResultWithOkBrand<()>, OptionBrand, _>(Err(Some(5))),
815 /// Some(Err(5))
816 /// );
817 /// ```
818 fn sequence<'a, F: Applicative, A: 'a + Clone>(
819 ta: Apply1L1T<'a, Self, Apply1L1T<'a, F, A>>
820 ) -> Apply1L1T<'a, F, Apply1L1T<'a, Self, A>>
821 where
822 Apply1L1T<'a, F, A>: Clone,
823 Apply1L1T<'a, Self, A>: Clone,
824 {
825 match ta {
826 Err(fe) => F::map(|e| Err(e), fe),
827 Ok(t) => F::pure(Ok(t)),
828 }
829 }
830}
831
832#[cfg(test)]
833mod tests {
834 use super::*;
835 use crate::{
836 brands::{OptionBrand, RcFnBrand},
837 classes::{functor::map, pointed::pure, semiapplicative::apply, semimonad::bind},
838 functions::{compose, identity},
839 };
840 use quickcheck_macros::quickcheck;
841
842 // Functor Laws
843
844 /// Tests the identity law for Functor.
845 #[quickcheck]
846 fn functor_identity(x: Result<i32, i32>) -> bool {
847 map::<ResultWithErrBrand<i32>, _, _, _>(identity, x) == x
848 }
849
850 /// Tests the composition law for Functor.
851 #[quickcheck]
852 fn functor_composition(x: Result<i32, i32>) -> bool {
853 let f = |x: i32| x.wrapping_add(1);
854 let g = |x: i32| x.wrapping_mul(2);
855 map::<ResultWithErrBrand<i32>, _, _, _>(compose(f, g), x)
856 == map::<ResultWithErrBrand<i32>, _, _, _>(
857 f,
858 map::<ResultWithErrBrand<i32>, _, _, _>(g, x),
859 )
860 }
861
862 // Applicative Laws
863
864 /// Tests the identity law for Applicative.
865 #[quickcheck]
866 fn applicative_identity(v: Result<i32, i32>) -> bool {
867 apply::<ResultWithErrBrand<i32>, _, _, RcFnBrand>(
868 pure::<ResultWithErrBrand<i32>, _>(<RcFnBrand as ClonableFn>::new(identity)),
869 v,
870 ) == v
871 }
872
873 /// Tests the homomorphism law for Applicative.
874 #[quickcheck]
875 fn applicative_homomorphism(x: i32) -> bool {
876 let f = |x: i32| x.wrapping_mul(2);
877 apply::<ResultWithErrBrand<i32>, _, _, RcFnBrand>(
878 pure::<ResultWithErrBrand<i32>, _>(<RcFnBrand as ClonableFn>::new(f)),
879 pure::<ResultWithErrBrand<i32>, _>(x),
880 ) == pure::<ResultWithErrBrand<i32>, _>(f(x))
881 }
882
883 /// Tests the composition law for Applicative.
884 #[quickcheck]
885 fn applicative_composition(
886 w: Result<i32, i32>,
887 u_is_ok: bool,
888 v_is_ok: bool,
889 ) -> bool {
890 let v_fn = |x: i32| x.wrapping_mul(2);
891 let u_fn = |x: i32| x.wrapping_add(1);
892
893 let v = if v_is_ok {
894 pure::<ResultWithErrBrand<i32>, _>(<RcFnBrand as ClonableFn>::new(v_fn))
895 } else {
896 Err(100)
897 };
898 let u = if u_is_ok {
899 pure::<ResultWithErrBrand<i32>, _>(<RcFnBrand as ClonableFn>::new(u_fn))
900 } else {
901 Err(200)
902 };
903
904 // RHS: u <*> (v <*> w)
905 let vw = apply::<ResultWithErrBrand<i32>, _, _, RcFnBrand>(v.clone(), w.clone());
906 let rhs = apply::<ResultWithErrBrand<i32>, _, _, RcFnBrand>(u.clone(), vw);
907
908 // LHS: pure(compose) <*> u <*> v <*> w
909 // equivalent to (u . v) <*> w
910 let uv = match (u, v) {
911 (Ok(uf), Ok(vf)) => {
912 let composed = move |x| uf(vf(x));
913 Ok(<RcFnBrand as ClonableFn>::new(composed))
914 }
915 (Err(e), _) => Err(e),
916 (_, Err(e)) => Err(e),
917 };
918
919 let lhs = apply::<ResultWithErrBrand<i32>, _, _, RcFnBrand>(uv, w);
920
921 lhs == rhs
922 }
923
924 /// Tests the interchange law for Applicative.
925 #[quickcheck]
926 fn applicative_interchange(y: i32) -> bool {
927 // u <*> pure y = pure ($ y) <*> u
928 let f = |x: i32| x.wrapping_mul(2);
929 let u = pure::<ResultWithErrBrand<i32>, _>(<RcFnBrand as ClonableFn>::new(f));
930
931 let lhs = apply::<ResultWithErrBrand<i32>, _, _, RcFnBrand>(
932 u.clone(),
933 pure::<ResultWithErrBrand<i32>, _>(y),
934 );
935
936 let rhs_fn = <RcFnBrand as ClonableFn>::new(move |f: std::rc::Rc<dyn Fn(i32) -> i32>| f(y));
937 let rhs = apply::<ResultWithErrBrand<i32>, _, _, RcFnBrand>(
938 pure::<ResultWithErrBrand<i32>, _>(rhs_fn),
939 u,
940 );
941
942 lhs == rhs
943 }
944
945 // Monad Laws
946
947 /// Tests the left identity law for Monad.
948 #[quickcheck]
949 fn monad_left_identity(a: i32) -> bool {
950 let f = |x: i32| -> Result<i32, i32> { Err(x.wrapping_mul(2)) };
951 bind::<ResultWithErrBrand<i32>, _, _, _>(pure::<ResultWithErrBrand<i32>, _>(a), f) == f(a)
952 }
953
954 /// Tests the right identity law for Monad.
955 #[quickcheck]
956 fn monad_right_identity(m: Result<i32, i32>) -> bool {
957 bind::<ResultWithErrBrand<i32>, _, _, _>(m, pure::<ResultWithErrBrand<i32>, _>) == m
958 }
959
960 /// Tests the associativity law for Monad.
961 #[quickcheck]
962 fn monad_associativity(m: Result<i32, i32>) -> bool {
963 let f = |x: i32| -> Result<i32, i32> { Err(x.wrapping_mul(2)) };
964 let g = |x: i32| -> Result<i32, i32> { Err(x.wrapping_add(1)) };
965 bind::<ResultWithErrBrand<i32>, _, _, _>(bind::<ResultWithErrBrand<i32>, _, _, _>(m, f), g)
966 == bind::<ResultWithErrBrand<i32>, _, _, _>(m, |x| {
967 bind::<ResultWithErrBrand<i32>, _, _, _>(f(x), g)
968 })
969 }
970
971 // Edge Cases
972
973 /// Tests `map` on `Err`.
974 #[test]
975 fn map_err() {
976 assert_eq!(
977 map::<ResultWithErrBrand<i32>, _, _, _>(|x: i32| x + 1, Err::<i32, i32>(1)),
978 Err(1)
979 );
980 }
981
982 /// Tests `bind` on `Err`.
983 #[test]
984 fn bind_err() {
985 assert_eq!(
986 bind::<ResultWithErrBrand<i32>, _, _, _>(Err::<i32, i32>(1), |x: i32| Ok(x + 1)),
987 Err(1)
988 );
989 }
990
991 /// Tests `bind` returning `Err`.
992 #[test]
993 fn bind_returning_err() {
994 assert_eq!(bind::<ResultWithErrBrand<i32>, _, _, _>(Ok(1), |_| Err::<i32, i32>(2)), Err(2));
995 }
996
997 /// Tests `fold_right` on `Err`.
998 #[test]
999 fn fold_right_err() {
1000 assert_eq!(
1001 crate::classes::foldable::fold_right::<ResultWithErrBrand<i32>, _, _, _>(
1002 |x: i32, acc| x + acc,
1003 0,
1004 Err(1)
1005 ),
1006 0
1007 );
1008 }
1009
1010 /// Tests `fold_left` on `Err`.
1011 #[test]
1012 fn fold_left_err() {
1013 assert_eq!(
1014 crate::classes::foldable::fold_left::<ResultWithErrBrand<i32>, _, _, _>(
1015 |acc, x: i32| acc + x,
1016 0,
1017 Err(1)
1018 ),
1019 0
1020 );
1021 }
1022
1023 /// Tests `traverse` on `Err`.
1024 #[test]
1025 fn traverse_err() {
1026 assert_eq!(
1027 crate::classes::traversable::traverse::<ResultWithErrBrand<i32>, OptionBrand, _, _, _>(
1028 |x: i32| Some(x + 1),
1029 Err(1)
1030 ),
1031 Some(Err(1))
1032 );
1033 }
1034
1035 /// Tests `traverse` returning `Err`.
1036 #[test]
1037 fn traverse_returning_err() {
1038 assert_eq!(
1039 crate::classes::traversable::traverse::<ResultWithErrBrand<i32>, OptionBrand, _, _, _>(
1040 |_: i32| None::<i32>,
1041 Ok(1)
1042 ),
1043 None
1044 );
1045 }
1046}