fp_library/types/result.rs
1//! Implementations for [`Result`].
2
3use crate::{
4 Apply,
5 brands::{ResultBrand, ResultWithErrBrand, ResultWithOkBrand},
6 classes::{
7 applicative::Applicative, apply_first::ApplyFirst, apply_second::ApplySecond,
8 clonable_fn::ClonableFn, foldable::Foldable, functor::Functor, lift::Lift, monoid::Monoid,
9 pointed::Pointed, semiapplicative::Semiapplicative, semimonad::Semimonad,
10 traversable::Traversable,
11 },
12 impl_kind,
13 kinds::*,
14};
15
16impl_kind! {
17 for ResultBrand {
18 type Of<A, B> = Result<B, A>;
19 }
20}
21
22// ResultWithErrBrand<E> (Functor over T)
23
24impl_kind! {
25 impl<E: 'static> for ResultWithErrBrand<E> {
26 type Of<'a, A: 'a>: 'a = Result<A, E>;
27 }
28}
29
30impl<E: 'static> Functor for ResultWithErrBrand<E> {
31 /// Maps a function over the value in the result.
32 ///
33 /// # Type Signature
34 ///
35 /// `forall a b e. Functor (Result e) => (a -> b, Result e a) -> Result e b`
36 ///
37 /// # Parameters
38 ///
39 /// * `f`: The function to apply.
40 /// * `fa`: The result to map over.
41 ///
42 /// # Returns
43 ///
44 /// A new result containing the result of applying the function, or the original error.
45 ///
46 /// # Examples
47 ///
48 /// ```
49 /// use fp_library::classes::functor::map;
50 /// use fp_library::brands::ResultWithErrBrand;
51 ///
52 /// assert_eq!(map::<ResultWithErrBrand<()>, _, _, _>(|x: i32| x * 2, Ok(5)), Ok(10));
53 /// assert_eq!(map::<ResultWithErrBrand<i32>, _, _, _>(|x: i32| x * 2, Err(1)), Err(1));
54 /// ```
55 fn map<'a, A: 'a, B: 'a, F>(
56 f: F,
57 fa: Apply!(brand: Self, signature: ('a, A: 'a) -> 'a),
58 ) -> Apply!(brand: Self, signature: ('a, B: 'a) -> 'a)
59 where
60 F: Fn(A) -> B + 'a,
61 {
62 fa.map(f)
63 }
64}
65
66impl<E: Clone + 'static> Lift for ResultWithErrBrand<E> {
67 /// Lifts a binary function into the result context.
68 ///
69 /// # Type Signature
70 ///
71 /// `forall a b c e. Lift (Result e) => ((a, b) -> c, Result e a, Result e b) -> Result e c`
72 ///
73 /// # Parameters
74 ///
75 /// * `f`: The binary function to apply.
76 /// * `fa`: The first result.
77 /// * `fb`: The second result.
78 ///
79 /// # Returns
80 ///
81 /// `Ok(f(a, b))` if both results are `Ok`, otherwise the first error encountered.
82 ///
83 /// # Examples
84 ///
85 /// ```
86 /// use fp_library::classes::lift::lift2;
87 /// use fp_library::brands::ResultWithErrBrand;
88 ///
89 /// assert_eq!(
90 /// lift2::<ResultWithErrBrand<()>, _, _, _, _>(|x: i32, y: i32| x + y, Ok(1), Ok(2)),
91 /// Ok(3)
92 /// );
93 /// assert_eq!(
94 /// lift2::<ResultWithErrBrand<i32>, _, _, _, _>(|x: i32, y: i32| x + y, Ok(1), Err(2)),
95 /// Err(2)
96 /// );
97 /// ```
98 fn lift2<'a, A, B, C, F>(
99 f: F,
100 fa: Apply!(brand: Self, signature: ('a, A: 'a) -> 'a),
101 fb: Apply!(brand: Self, signature: ('a, B: 'a) -> 'a),
102 ) -> Apply!(brand: Self, signature: ('a, C: 'a) -> 'a)
103 where
104 F: Fn(A, B) -> C + 'a,
105 A: Clone + 'a,
106 B: Clone + 'a,
107 C: 'a,
108 {
109 match (fa, fb) {
110 (Ok(a), Ok(b)) => Ok(f(a, b)),
111 (Err(e), _) => Err(e),
112 (_, Err(e)) => Err(e),
113 }
114 }
115}
116
117impl<E: 'static> Pointed for ResultWithErrBrand<E> {
118 /// Wraps a value in a result.
119 ///
120 /// # Type Signature
121 ///
122 /// `forall a e. Pointed (Result e) => a -> Result e a`
123 ///
124 /// # Parameters
125 ///
126 /// * `a`: The value to wrap.
127 ///
128 /// # Returns
129 ///
130 /// `Ok(a)`.
131 ///
132 /// # Examples
133 ///
134 /// ```
135 /// use fp_library::classes::pointed::pure;
136 /// use fp_library::brands::ResultWithErrBrand;
137 ///
138 /// assert_eq!(pure::<ResultWithErrBrand<()>, _>(5), Ok(5));
139 /// ```
140 fn pure<'a, A: 'a>(a: A) -> Apply!(brand: Self, signature: ('a, A: 'a) -> 'a) {
141 Ok(a)
142 }
143}
144
145impl<E: Clone + 'static> ApplyFirst for ResultWithErrBrand<E> {}
146impl<E: Clone + 'static> ApplySecond for ResultWithErrBrand<E> {}
147
148impl<E: Clone + 'static> Semiapplicative for ResultWithErrBrand<E> {
149 /// Applies a wrapped function to a wrapped value.
150 ///
151 /// # Type Signature
152 ///
153 /// `forall a b e. Semiapplicative (Result e) => (Result e (a -> b), Result e a) -> Result e b`
154 ///
155 /// # Parameters
156 ///
157 /// * `ff`: The result containing the function.
158 /// * `fa`: The result containing the value.
159 ///
160 /// # Returns
161 ///
162 /// `Ok(f(a))` if both are `Ok`, otherwise the first error encountered.
163 ///
164 /// # Examples
165 ///
166 /// ```
167 /// use fp_library::classes::semiapplicative::apply;
168 /// use fp_library::classes::clonable_fn::ClonableFn;
169 /// use fp_library::brands::ResultWithErrBrand;
170 /// use fp_library::brands::RcFnBrand;
171 /// use std::rc::Rc;
172 ///
173 /// let f = Ok(<RcFnBrand as ClonableFn>::new(|x: i32| x * 2));
174 /// assert_eq!(apply::<ResultWithErrBrand<()>, _, _, RcFnBrand>(f, Ok(5)), Ok(10));
175 /// ```
176 fn apply<'a, A: 'a + Clone, B: 'a, FnBrand: 'a + ClonableFn>(
177 ff: Apply!(brand: Self, signature: ('a, Apply!(brand: FnBrand, kind: ClonableFn, lifetimes: ('a), types: (A, B)): 'a) -> 'a),
178 fa: Apply!(brand: Self, signature: ('a, A: 'a) -> 'a),
179 ) -> Apply!(brand: Self, signature: ('a, B: 'a) -> 'a) {
180 match (ff, fa) {
181 (Ok(f), Ok(a)) => Ok(f(a)),
182 (Err(e), _) => Err(e),
183 (_, Err(e)) => Err(e),
184 }
185 }
186}
187
188impl<E: Clone + 'static> Semimonad for ResultWithErrBrand<E> {
189 /// Chains result computations.
190 ///
191 /// # Type Signature
192 ///
193 /// `forall a b e. Semimonad (Result e) => (Result e a, a -> Result e b) -> Result e b`
194 ///
195 /// # Parameters
196 ///
197 /// * `ma`: The first result.
198 /// * `f`: The function to apply to the value inside the result.
199 ///
200 /// # Returns
201 ///
202 /// The result of applying `f` to the value if `ma` is `Ok`, otherwise the original error.
203 ///
204 /// # Examples
205 ///
206 /// ```
207 /// use fp_library::classes::semimonad::bind;
208 /// use fp_library::brands::ResultWithErrBrand;
209 ///
210 /// assert_eq!(
211 /// bind::<ResultWithErrBrand<()>, _, _, _>(Ok(5), |x| Ok(x * 2)),
212 /// Ok(10)
213 /// );
214 /// ```
215 fn bind<'a, A: 'a, B: 'a, F>(
216 ma: Apply!(brand: Self, signature: ('a, A: 'a) -> 'a),
217 f: F,
218 ) -> Apply!(brand: Self, signature: ('a, B: 'a) -> 'a)
219 where
220 F: Fn(A) -> Apply!(brand: Self, signature: ('a, B: 'a) -> 'a) + 'a,
221 {
222 ma.and_then(f)
223 }
224}
225
226impl<E: 'static> Foldable for ResultWithErrBrand<E> {
227 /// Folds the result from the right.
228 ///
229 /// # Type Signature
230 ///
231 /// `forall a b e. Foldable (Result e) => ((a, b) -> b, b, Result e a) -> b`
232 ///
233 /// # Parameters
234 ///
235 /// * `f`: The folding function.
236 /// * `init`: The initial value.
237 /// * `fa`: The result to fold.
238 ///
239 /// # Returns
240 ///
241 /// `f(a, init)` if `fa` is `Ok(a)`, otherwise `init`.
242 ///
243 /// # Examples
244 ///
245 /// ```
246 /// use fp_library::classes::foldable::fold_right;
247 /// use fp_library::brands::ResultWithErrBrand;
248 ///
249 /// assert_eq!(fold_right::<ResultWithErrBrand<()>, _, _, _>(|x, acc| x + acc, 0, Ok(5)), 5);
250 /// assert_eq!(fold_right::<ResultWithErrBrand<i32>, _, _, _>(|x: i32, acc| x + acc, 0, Err(1)), 0);
251 /// ```
252 fn fold_right<'a, A: 'a, B: 'a, F>(
253 f: F,
254 init: B,
255 fa: Apply!(brand: Self, signature: ('a, A: 'a) -> 'a),
256 ) -> B
257 where
258 F: Fn(A, B) -> B + 'a,
259 {
260 match fa {
261 Ok(a) => f(a, init),
262 Err(_) => init,
263 }
264 }
265
266 /// Folds the result from the left.
267 ///
268 /// # Type Signature
269 ///
270 /// `forall a b e. Foldable (Result e) => ((b, a) -> b, b, Result e a) -> b`
271 ///
272 /// # Parameters
273 ///
274 /// * `f`: The folding function.
275 /// * `init`: The initial value.
276 /// * `fa`: The result to fold.
277 ///
278 /// # Returns
279 ///
280 /// `f(init, a)` if `fa` is `Ok(a)`, otherwise `init`.
281 ///
282 /// # Examples
283 ///
284 /// ```
285 /// use fp_library::classes::foldable::fold_left;
286 /// use fp_library::brands::ResultWithErrBrand;
287 ///
288 /// assert_eq!(fold_left::<ResultWithErrBrand<()>, _, _, _>(|acc, x| acc + x, 0, Ok(5)), 5);
289 /// ```
290 fn fold_left<'a, A: 'a, B: 'a, F>(
291 f: F,
292 init: B,
293 fa: Apply!(brand: Self, signature: ('a, A: 'a) -> 'a),
294 ) -> B
295 where
296 F: Fn(B, A) -> B + 'a,
297 {
298 match fa {
299 Ok(a) => f(init, a),
300 Err(_) => init,
301 }
302 }
303
304 /// Maps the value to a monoid and returns it.
305 ///
306 /// # Type Signature
307 ///
308 /// `forall a m e. (Foldable (Result e), Monoid m) => ((a) -> m, Result e a) -> m`
309 ///
310 /// # Parameters
311 ///
312 /// * `f`: The mapping function.
313 /// * `fa`: The result to fold.
314 ///
315 /// # Returns
316 ///
317 /// `f(a)` if `fa` is `Ok(a)`, otherwise `M::empty()`.
318 ///
319 /// # Examples
320 ///
321 /// ```
322 /// use fp_library::classes::foldable::fold_map;
323 /// use fp_library::brands::ResultWithErrBrand;
324 /// use fp_library::types::string;
325 ///
326 /// assert_eq!(
327 /// fold_map::<ResultWithErrBrand<()>, _, _, _>(|x: i32| x.to_string(), Ok(5)),
328 /// "5".to_string()
329 /// );
330 /// ```
331 fn fold_map<'a, A: 'a, M, F>(
332 f: F,
333 fa: Apply!(brand: Self, signature: ('a, A: 'a) -> 'a),
334 ) -> M
335 where
336 M: Monoid + 'a,
337 F: Fn(A) -> M + 'a,
338 {
339 match fa {
340 Ok(a) => f(a),
341 Err(_) => M::empty(),
342 }
343 }
344}
345
346impl<E: Clone + 'static> Traversable for ResultWithErrBrand<E> {
347 /// Traverses the result with an applicative function.
348 ///
349 /// # Type Signature
350 ///
351 /// `forall a b f e. (Traversable (Result e), Applicative f) => (a -> f b, Result e a) -> f (Result e b)`
352 ///
353 /// # Parameters
354 ///
355 /// * `f`: The function to apply.
356 /// * `ta`: The result to traverse.
357 ///
358 /// # Returns
359 ///
360 /// The result wrapped in the applicative context.
361 ///
362 /// # Examples
363 ///
364 /// ```
365 /// use fp_library::classes::traversable::traverse;
366 /// use fp_library::brands::{ResultWithErrBrand, OptionBrand};
367 ///
368 /// assert_eq!(
369 /// traverse::<ResultWithErrBrand<()>, OptionBrand, _, _, _>(|x| Some(x * 2), Ok(5)),
370 /// Some(Ok(10))
371 /// );
372 /// ```
373 fn traverse<'a, F: Applicative, A: 'a + Clone, B: 'a + Clone, Func>(
374 f: Func,
375 ta: Apply!(brand: Self, signature: ('a, A: 'a) -> 'a),
376 ) -> Apply!(brand: F, signature: ('a, Apply!(brand: Self, signature: ('a, B: 'a) -> 'a): 'a) -> 'a)
377 where
378 Func: Fn(A) -> Apply!(brand: F, signature: ('a, B: 'a) -> 'a) + 'a,
379 Apply!(brand: Self, signature: ('a, B: 'a) -> 'a): Clone,
380 {
381 match ta {
382 Ok(a) => F::map(|b| Ok(b), f(a)),
383 Err(e) => F::pure(Err(e)),
384 }
385 }
386
387 /// Sequences a result of applicative.
388 ///
389 /// # Type Signature
390 ///
391 /// `forall a f e. (Traversable (Result e), Applicative f) => (Result e (f a)) -> f (Result e a)`
392 ///
393 /// # Parameters
394 ///
395 /// * `ta`: The result containing the applicative value.
396 ///
397 /// # Returns
398 ///
399 /// The result wrapped in the applicative context.
400 ///
401 /// # Examples
402 ///
403 /// ```
404 /// use fp_library::classes::traversable::sequence;
405 /// use fp_library::brands::{ResultWithErrBrand, OptionBrand};
406 ///
407 /// assert_eq!(
408 /// sequence::<ResultWithErrBrand<()>, OptionBrand, _>(Ok(Some(5))),
409 /// Some(Ok(5))
410 /// );
411 /// ```
412 fn sequence<'a, F: Applicative, A: 'a + Clone>(
413 ta: Apply!(brand: Self, signature: ('a, Apply!(brand: F, signature: ('a, A: 'a) -> 'a): 'a) -> 'a)
414 ) -> Apply!(brand: F, signature: ('a, Apply!(brand: Self, signature: ('a, A: 'a) -> 'a): 'a) -> 'a)
415 where
416 Apply!(brand: F, signature: ('a, A: 'a) -> 'a): Clone,
417 Apply!(brand: Self, signature: ('a, A: 'a) -> 'a): Clone,
418 {
419 match ta {
420 Ok(fa) => F::map(|a| Ok(a), fa),
421 Err(e) => F::pure(Err(e)),
422 }
423 }
424}
425
426// ResultWithOkBrand<T> (Functor over E)
427
428impl_kind! {
429 impl<T: 'static> for ResultWithOkBrand<T> {
430 type Of<'a, A: 'a>: 'a = Result<T, A>;
431 }
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: Apply!(brand: Self, signature: ('a, A: 'a) -> 'a),
462 ) -> Apply!(brand: Self, signature: ('a, B: 'a) -> 'a)
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: Apply!(brand: Self, signature: ('a, A: 'a) -> 'a),
504 fb: Apply!(brand: Self, signature: ('a, B: 'a) -> 'a),
505 ) -> Apply!(brand: Self, signature: ('a, C: 'a) -> 'a)
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) -> Apply!(brand: Self, signature: ('a, A: 'a) -> '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: Apply!(brand: Self, signature: ('a, Apply!(brand: FnBrand, kind: ClonableFn, lifetimes: ('a), types: (A, B)): 'a) -> 'a),
581 fa: Apply!(brand: Self, signature: ('a, A: 'a) -> 'a),
582 ) -> Apply!(brand: Self, signature: ('a, B: 'a) -> 'a) {
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: Apply!(brand: Self, signature: ('a, A: 'a) -> 'a),
620 f: F,
621 ) -> Apply!(brand: Self, signature: ('a, B: 'a) -> 'a)
622 where
623 F: Fn(A) -> Apply!(brand: Self, signature: ('a, B: 'a) -> 'a) + '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: Apply!(brand: Self, signature: ('a, A: 'a) -> '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: Apply!(brand: Self, signature: ('a, A: 'a) -> '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: Apply!(brand: Self, signature: ('a, A: 'a) -> '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: Apply!(brand: Self, signature: ('a, A: 'a) -> 'a),
782 ) -> Apply!(brand: F, signature: ('a, Apply!(brand: Self, signature: ('a, B: 'a) -> 'a): 'a) -> 'a)
783 where
784 Func: Fn(A) -> Apply!(brand: F, signature: ('a, B: 'a) -> 'a) + 'a,
785 Apply!(brand: Self, signature: ('a, B: 'a) -> 'a): 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: Apply!(brand: Self, signature: ('a, Apply!(brand: F, signature: ('a, A: 'a) -> 'a): 'a) -> 'a)
820 ) -> Apply!(brand: F, signature: ('a, Apply!(brand: Self, signature: ('a, A: 'a) -> 'a): 'a) -> 'a)
821 where
822 Apply!(brand: F, signature: ('a, A: 'a) -> 'a): Clone,
823 Apply!(brand: Self, signature: ('a, A: 'a) -> '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}