fp_library/types/result.rs
1//! Implementations for [`Result`].
2//!
3//! This module provides implementations of various type classes for the `Result` type.
4//! `Result` can be treated as a functor/monad in two ways:
5//! 1. `ResultWithErrBrand<E>`: Functor over the success value `T` (fixing `E`). This is the standard `Result` monad.
6//! 2. `ResultWithOkBrand<T>`: Functor over the error value `E` (fixing `T`).
7
8use crate::{
9 Apply,
10 brands::{ResultBrand, ResultWithErrBrand, ResultWithOkBrand},
11 classes::{
12 applicative::Applicative, apply_first::ApplyFirst, apply_second::ApplySecond,
13 clonable_fn::ClonableFn, foldable::Foldable, functor::Functor, lift::Lift, monoid::Monoid,
14 par_foldable::ParFoldable, pointed::Pointed, semiapplicative::Semiapplicative,
15 semimonad::Semimonad, send_clonable_fn::SendClonableFn, traversable::Traversable,
16 },
17 impl_kind,
18 kinds::*,
19};
20
21impl_kind! {
22 for ResultBrand {
23 type Of<A, B> = Result<B, A>;
24 }
25}
26
27// ResultWithErrBrand<E> (Functor over T)
28
29impl_kind! {
30 impl<E: 'static> for ResultWithErrBrand<E> {
31 type Of<'a, A: 'a>: 'a = Result<A, E>;
32 }
33}
34
35impl<E: 'static> Functor for ResultWithErrBrand<E> {
36 /// Maps a function over the value in the result.
37 ///
38 /// This method applies a function to the value inside the result if it is `Ok`, producing a new result with the transformed value. If the result is `Err`, it is returned unchanged.
39 ///
40 /// ### Type Signature
41 ///
42 /// `forall a b e. Functor (Result e) => (a -> b, Result e a) -> Result e b`
43 ///
44 /// ### Type Parameters
45 ///
46 /// * `F`: The type of the function to apply.
47 /// * `A`: The type of the value inside the result.
48 /// * `B`: The type of the result of applying the function.
49 ///
50 /// ### Parameters
51 ///
52 /// * `f`: The function to apply.
53 /// * `fa`: The result to map over.
54 ///
55 /// ### Returns
56 ///
57 /// A new result containing the result of applying the function, or the original error.
58 ///
59 /// ### Examples
60 ///
61 /// ```
62 /// use fp_library::classes::functor::map;
63 /// use fp_library::brands::ResultWithErrBrand;
64 ///
65 /// assert_eq!(map::<ResultWithErrBrand<()>, _, _, _>(|x: i32| x * 2, Ok(5)), Ok(10));
66 /// assert_eq!(map::<ResultWithErrBrand<i32>, _, _, _>(|x: i32| x * 2, Err(1)), Err(1));
67 /// ```
68 fn map<'a, F, A: 'a, B: 'a>(
69 f: F,
70 fa: Apply!(brand: Self, signature: ('a, A: 'a) -> 'a),
71 ) -> Apply!(brand: Self, signature: ('a, B: 'a) -> 'a)
72 where
73 F: Fn(A) -> B + 'a,
74 {
75 fa.map(f)
76 }
77}
78
79impl<E: Clone + 'static> Lift for ResultWithErrBrand<E> {
80 /// Lifts a binary function into the result context.
81 ///
82 /// This method lifts a binary function to operate on values within the result context.
83 ///
84 /// ### Type Signature
85 ///
86 /// `forall a b c e. Lift (Result e) => ((a, b) -> c, Result e a, Result e b) -> Result e c`
87 ///
88 /// ### Type Parameters
89 ///
90 /// * `F`: The type of the binary function.
91 /// * `A`: The type of the first value.
92 /// * `B`: The type of the second value.
93 /// * `C`: The type of the result.
94 ///
95 /// ### Parameters
96 ///
97 /// * `f`: The binary function to apply.
98 /// * `fa`: The first result.
99 /// * `fb`: The second result.
100 ///
101 /// ### Returns
102 ///
103 /// `Ok(f(a, b))` if both results are `Ok`, otherwise the first error encountered.
104 ///
105 /// ### Examples
106 ///
107 /// ```
108 /// use fp_library::classes::lift::lift2;
109 /// use fp_library::brands::ResultWithErrBrand;
110 ///
111 /// assert_eq!(
112 /// lift2::<ResultWithErrBrand<()>, _, _, _, _>(|x: i32, y: i32| x + y, Ok(1), Ok(2)),
113 /// Ok(3)
114 /// );
115 /// assert_eq!(
116 /// lift2::<ResultWithErrBrand<i32>, _, _, _, _>(|x: i32, y: i32| x + y, Ok(1), Err(2)),
117 /// Err(2)
118 /// );
119 /// assert_eq!(
120 /// lift2::<ResultWithErrBrand<i32>, _, _, _, _>(|x: i32, y: i32| x + y, Err(1), Ok(2)),
121 /// Err(1)
122 /// );
123 /// assert_eq!(
124 /// lift2::<ResultWithErrBrand<i32>, _, _, _, _>(|x: i32, y: i32| x + y, Err(1), Err(2)),
125 /// Err(1)
126 /// );
127 /// ```
128 fn lift2<'a, F, A, B, C>(
129 f: F,
130 fa: Apply!(brand: Self, signature: ('a, A: 'a) -> 'a),
131 fb: Apply!(brand: Self, signature: ('a, B: 'a) -> 'a),
132 ) -> Apply!(brand: Self, signature: ('a, C: 'a) -> 'a)
133 where
134 F: Fn(A, B) -> C + 'a,
135 A: Clone + 'a,
136 B: Clone + 'a,
137 C: 'a,
138 {
139 match (fa, fb) {
140 (Ok(a), Ok(b)) => Ok(f(a, b)),
141 (Err(e), _) => Err(e),
142 (_, Err(e)) => Err(e),
143 }
144 }
145}
146
147impl<E: 'static> Pointed for ResultWithErrBrand<E> {
148 /// Wraps a value in a result.
149 ///
150 /// This method wraps a value in the `Ok` variant of a `Result`.
151 ///
152 /// ### Type Signature
153 ///
154 /// `forall a e. Pointed (Result e) => a -> Result e a`
155 ///
156 /// ### Type Parameters
157 ///
158 /// * `A`: The type of the value to wrap.
159 ///
160 /// ### Parameters
161 ///
162 /// * `a`: The value to wrap.
163 ///
164 /// ### Returns
165 ///
166 /// `Ok(a)`.
167 ///
168 /// ### Examples
169 ///
170 /// ```
171 /// use fp_library::classes::pointed::pure;
172 /// use fp_library::brands::ResultWithErrBrand;
173 ///
174 /// assert_eq!(pure::<ResultWithErrBrand<()>, _>(5), Ok(5));
175 /// ```
176 fn pure<'a, A: 'a>(a: A) -> Apply!(brand: Self, signature: ('a, A: 'a) -> 'a) {
177 Ok(a)
178 }
179}
180
181impl<E: Clone + 'static> ApplyFirst for ResultWithErrBrand<E> {}
182impl<E: Clone + 'static> ApplySecond for ResultWithErrBrand<E> {}
183
184impl<E: Clone + 'static> Semiapplicative for ResultWithErrBrand<E> {
185 /// Applies a wrapped function to a wrapped value.
186 ///
187 /// This method applies a function wrapped in a result to a value wrapped in a result.
188 ///
189 /// ### Type Signature
190 ///
191 /// `forall a b e. Semiapplicative (Result e) => (Result e (a -> b), Result e a) -> Result e b`
192 ///
193 /// ### Type Parameters
194 ///
195 /// * `FnBrand`: The brand of the clonable function wrapper.
196 /// * `A`: The type of the input value.
197 /// * `B`: The type of the output value.
198 ///
199 /// ### Parameters
200 ///
201 /// * `ff`: The result containing the function.
202 /// * `fa`: The result containing the value.
203 ///
204 /// ### Returns
205 ///
206 /// `Ok(f(a))` if both are `Ok`, otherwise the first error encountered.
207 ///
208 /// ### Examples
209 ///
210 /// ```
211 /// use fp_library::classes::semiapplicative::apply;
212 /// use fp_library::classes::clonable_fn::ClonableFn;
213 /// use fp_library::brands::ResultWithErrBrand;
214 /// use fp_library::brands::RcFnBrand;
215 /// use std::rc::Rc;
216 ///
217 /// let f: Result<_, ()> = Ok(<RcFnBrand as ClonableFn>::new(|x: i32| x * 2));
218 /// assert_eq!(apply::<RcFnBrand, ResultWithErrBrand<()>, _, _>(f, Ok(5)), Ok(10));
219 /// let f: Result<_, i32> = Ok(<RcFnBrand as ClonableFn>::new(|x: i32| x * 2));
220 /// assert_eq!(apply::<RcFnBrand, ResultWithErrBrand<i32>, _, _>(f, Err(1)), Err(1));
221 ///
222 /// let f_err: Result<Rc<dyn Fn(i32) -> i32>, i32> = Err(1);
223 /// assert_eq!(apply::<RcFnBrand, ResultWithErrBrand<i32>, _, _>(f_err, Ok(5)), Err(1));
224 /// ```
225 fn apply<'a, FnBrand: 'a + ClonableFn, A: 'a + Clone, B: 'a>(
226 ff: Apply!(brand: Self, signature: ('a, Apply!(brand: FnBrand, kind: ClonableFn, lifetimes: ('a), types: (A, B)): 'a) -> 'a),
227 fa: Apply!(brand: Self, signature: ('a, A: 'a) -> 'a),
228 ) -> Apply!(brand: Self, signature: ('a, B: 'a) -> 'a) {
229 match (ff, fa) {
230 (Ok(f), Ok(a)) => Ok(f(a)),
231 (Err(e), _) => Err(e),
232 (_, Err(e)) => Err(e),
233 }
234 }
235}
236
237impl<E: Clone + 'static> Semimonad for ResultWithErrBrand<E> {
238 /// Chains result computations.
239 ///
240 /// This method chains two computations, where the second computation depends on the result of the first.
241 ///
242 /// ### Type Signature
243 ///
244 /// `forall a b e. Semimonad (Result e) => (Result e a, a -> Result e b) -> Result e b`
245 ///
246 /// ### Type Parameters
247 ///
248 /// * `F`: The type of the function to apply.
249 /// * `A`: The type of the result of the first computation.
250 /// * `B`: The type of the result of the second computation.
251 ///
252 /// ### Parameters
253 ///
254 /// * `ma`: The first result.
255 /// * `f`: The function to apply to the value inside the result.
256 ///
257 /// ### Returns
258 ///
259 /// The result of applying `f` to the value if `ma` is `Ok`, otherwise the original error.
260 ///
261 /// ### Examples
262 ///
263 /// ```
264 /// use fp_library::classes::semimonad::bind;
265 /// use fp_library::brands::ResultWithErrBrand;
266 ///
267 /// assert_eq!(
268 /// bind::<ResultWithErrBrand<()>, _, _, _>(Ok(5), |x| Ok(x * 2)),
269 /// Ok(10)
270 /// );
271 /// assert_eq!(
272 /// bind::<ResultWithErrBrand<i32>, _, _, _>(Ok(5), |_| Err::<i32, _>(1)),
273 /// Err(1)
274 /// );
275 /// assert_eq!(
276 /// bind::<ResultWithErrBrand<i32>, _, _, _>(Err(1), |x: i32| Ok(x * 2)),
277 /// Err(1)
278 /// );
279 /// ```
280 fn bind<'a, F, A: 'a, B: 'a>(
281 ma: Apply!(brand: Self, signature: ('a, A: 'a) -> 'a),
282 f: F,
283 ) -> Apply!(brand: Self, signature: ('a, B: 'a) -> 'a)
284 where
285 F: Fn(A) -> Apply!(brand: Self, signature: ('a, B: 'a) -> 'a) + 'a,
286 {
287 ma.and_then(f)
288 }
289}
290
291impl<E: 'static> Foldable for ResultWithErrBrand<E> {
292 /// Folds the result from the right.
293 ///
294 /// This method performs a right-associative fold of the result.
295 ///
296 /// ### Type Signature
297 ///
298 /// `forall a b e. Foldable (Result e) => ((a, b) -> b, b, Result e a) -> b`
299 ///
300 /// ### Type Parameters
301 ///
302 /// * `FnBrand`: The brand of the clonable function to use.
303 /// * `F`: The type of the folding function.
304 /// * `A`: The type of the elements in the structure.
305 /// * `B`: The type of the accumulator.
306 ///
307 /// ### Parameters
308 ///
309 /// * `func`: The folding function.
310 /// * `initial`: The initial value.
311 /// * `fa`: The result to fold.
312 ///
313 /// ### Returns
314 ///
315 /// `func(a, initial)` if `fa` is `Ok(a)`, otherwise `initial`.
316 ///
317 /// ### Examples
318 ///
319 /// ```
320 /// use fp_library::classes::foldable::fold_right;
321 /// use fp_library::brands::ResultWithErrBrand;
322 /// use fp_library::brands::RcFnBrand;
323 ///
324 /// assert_eq!(fold_right::<RcFnBrand, ResultWithErrBrand<()>, _, _, _>(|x, acc| x + acc, 0, Ok(5)), 5);
325 /// assert_eq!(fold_right::<RcFnBrand, ResultWithErrBrand<i32>, _, _, _>(|x: i32, acc| x + acc, 0, Err(1)), 0);
326 /// ```
327 fn fold_right<'a, FnBrand, F, A: 'a, B: 'a>(
328 func: F,
329 initial: B,
330 fa: Apply!(brand: Self, signature: ('a, A: 'a) -> 'a),
331 ) -> B
332 where
333 F: Fn(A, B) -> B + 'a,
334 FnBrand: ClonableFn + 'a,
335 {
336 match fa {
337 Ok(a) => func(a, initial),
338 Err(_) => initial,
339 }
340 }
341
342 /// Folds the result from the left.
343 ///
344 /// This method performs a left-associative fold of the result.
345 ///
346 /// ### Type Signature
347 ///
348 /// `forall a b e. Foldable (Result e) => ((b, a) -> b, b, Result e a) -> b`
349 ///
350 /// ### Type Parameters
351 ///
352 /// * `FnBrand`: The brand of the clonable function to use.
353 /// * `Func`: The type of the folding function.
354 /// * `A`: The type of the elements in the structure.
355 /// * `B`: The type of the accumulator.
356 ///
357 /// ### Parameters
358 ///
359 /// * `func`: The folding function.
360 /// * `initial`: The initial value.
361 /// * `fa`: The result to fold.
362 ///
363 /// ### Returns
364 ///
365 /// `func(initial, a)` if `fa` is `Ok(a)`, otherwise `initial`.
366 ///
367 /// ### Examples
368 ///
369 /// ```
370 /// use fp_library::classes::foldable::fold_left;
371 /// use fp_library::brands::ResultWithErrBrand;
372 /// use fp_library::brands::RcFnBrand;
373 ///
374 /// assert_eq!(fold_left::<RcFnBrand, ResultWithErrBrand<()>, _, _, _>(|acc, x| acc + x, 0, Ok(5)), 5);
375 /// assert_eq!(fold_left::<RcFnBrand, ResultWithErrBrand<i32>, _, _, _>(|acc, x: i32| acc + x, 0, Err(1)), 0);
376 /// ```
377 fn fold_left<'a, FnBrand, F, A: 'a, B: 'a>(
378 func: F,
379 initial: B,
380 fa: Apply!(brand: Self, signature: ('a, A: 'a) -> 'a),
381 ) -> B
382 where
383 F: Fn(B, A) -> B + 'a,
384 FnBrand: ClonableFn + 'a,
385 {
386 match fa {
387 Ok(a) => func(initial, a),
388 Err(_) => initial,
389 }
390 }
391
392 /// Maps the value to a monoid and returns it.
393 ///
394 /// This method maps the element of the result to a monoid and then returns it.
395 ///
396 /// ### Type Signature
397 ///
398 /// `forall a m e. (Foldable (Result e), Monoid m) => ((a) -> m, Result e a) -> m`
399 ///
400 /// ### Type Parameters
401 ///
402 /// * `FnBrand`: The brand of the clonable function to use.
403 /// * `Func`: The type of the mapping function.
404 /// * `A`: The type of the elements in the structure.
405 /// * `M`: The type of the monoid.
406 ///
407 /// ### Parameters
408 ///
409 /// * `func`: The mapping function.
410 /// * `fa`: The result to fold.
411 ///
412 /// ### Returns
413 ///
414 /// `func(a)` if `fa` is `Ok(a)`, otherwise `M::empty()`.
415 ///
416 /// ### Examples
417 ///
418 /// ```
419 /// use fp_library::classes::foldable::fold_map;
420 /// use fp_library::brands::ResultWithErrBrand;
421 /// use fp_library::types::string;
422 /// use fp_library::brands::RcFnBrand;
423 ///
424 /// assert_eq!(
425 /// fold_map::<RcFnBrand, ResultWithErrBrand<()>, _, _, _>(|x: i32| x.to_string(), Ok(5)),
426 /// "5".to_string()
427 /// );
428 /// assert_eq!(
429 /// fold_map::<RcFnBrand, ResultWithErrBrand<i32>, _, _, _>(|x: i32| x.to_string(), Err(1)),
430 /// "".to_string()
431 /// );
432 /// ```
433 fn fold_map<'a, FnBrand, F, A: 'a, M>(
434 func: F,
435 fa: Apply!(brand: Self, signature: ('a, A: 'a) -> 'a),
436 ) -> M
437 where
438 M: Monoid + 'a,
439 F: Fn(A) -> M + 'a,
440 FnBrand: ClonableFn + 'a,
441 {
442 match fa {
443 Ok(a) => func(a),
444 Err(_) => M::empty(),
445 }
446 }
447}
448
449impl<E: Clone + 'static> Traversable for ResultWithErrBrand<E> {
450 /// Traverses the result with an applicative function.
451 ///
452 /// This method maps the element of the result to a computation, evaluates it, and combines the result into an applicative context.
453 ///
454 /// ### Type Signature
455 ///
456 /// `forall a b f e. (Traversable (Result e), Applicative f) => (a -> f b, Result e a) -> f (Result e b)`
457 ///
458 /// ### Type Parameters
459 ///
460 /// * `F`: The applicative context.
461 /// * `Func`: The type of the function to apply.
462 /// * `A`: The type of the elements in the traversable structure.
463 /// * `B`: The type of the elements in the resulting traversable structure.
464 ///
465 /// ### Parameters
466 ///
467 /// * `func`: The function to apply.
468 /// * `ta`: The result to traverse.
469 ///
470 /// ### Returns
471 ///
472 /// The result wrapped in the applicative context.
473 ///
474 /// ### Examples
475 ///
476 /// ```
477 /// use fp_library::classes::traversable::traverse;
478 /// use fp_library::brands::{ResultWithErrBrand, OptionBrand};
479 ///
480 /// assert_eq!(
481 /// traverse::<ResultWithErrBrand<()>, OptionBrand, _, _, _>(|x| Some(x * 2), Ok(5)),
482 /// Some(Ok(10))
483 /// );
484 /// assert_eq!(
485 /// traverse::<ResultWithErrBrand<i32>, OptionBrand, _, _, _>(|x: i32| Some(x * 2), Err(1)),
486 /// Some(Err(1))
487 /// );
488 /// assert_eq!(
489 /// traverse::<ResultWithErrBrand<()>, OptionBrand, _, _, _>(|_| None::<i32>, Ok(5)),
490 /// None
491 /// );
492 /// ```
493 fn traverse<'a, F: Applicative, Func, A: 'a + Clone, B: 'a + Clone>(
494 func: Func,
495 ta: Apply!(brand: Self, signature: ('a, A: 'a) -> 'a),
496 ) -> Apply!(brand: F, signature: ('a, Apply!(brand: Self, signature: ('a, B: 'a) -> 'a): 'a) -> 'a)
497 where
498 Func: Fn(A) -> Apply!(brand: F, signature: ('a, B: 'a) -> 'a) + 'a,
499 Apply!(brand: Self, signature: ('a, B: 'a) -> 'a): Clone,
500 {
501 match ta {
502 Ok(a) => F::map(|b| Ok(b), func(a)),
503 Err(e) => F::pure(Err(e)),
504 }
505 }
506
507 /// Sequences a result of applicative.
508 ///
509 /// This method evaluates the computation inside the result and accumulates the result into an applicative context.
510 ///
511 /// ### Type Signature
512 ///
513 /// `forall a f e. (Traversable (Result e), Applicative f) => (Result e (f a)) -> f (Result e a)`
514 ///
515 /// ### Type Parameters
516 ///
517 /// * `F`: The applicative context.
518 /// * `A`: The type of the elements in the traversable structure.
519 ///
520 /// ### Parameters
521 ///
522 /// * `ta`: The result containing the applicative value.
523 ///
524 /// ### Returns
525 ///
526 /// The result wrapped in the applicative context.
527 ///
528 /// ### Examples
529 ///
530 /// ```
531 /// use fp_library::classes::traversable::sequence;
532 /// use fp_library::brands::{ResultWithErrBrand, OptionBrand};
533 ///
534 /// assert_eq!(
535 /// sequence::<ResultWithErrBrand<()>, OptionBrand, _>(Ok(Some(5))),
536 /// Some(Ok(5))
537 /// );
538 /// assert_eq!(
539 /// sequence::<ResultWithErrBrand<i32>, OptionBrand, i32>(Err::<Option<i32>, _>(1)),
540 /// Some(Err::<i32, i32>(1))
541 /// );
542 /// assert_eq!(
543 /// sequence::<ResultWithErrBrand<()>, OptionBrand, _>(Ok(None::<i32>)),
544 /// None
545 /// );
546 /// ```
547 fn sequence<'a, F: Applicative, A: 'a + Clone>(
548 ta: Apply!(brand: Self, signature: ('a, Apply!(brand: F, signature: ('a, A: 'a) -> 'a): 'a) -> 'a)
549 ) -> Apply!(brand: F, signature: ('a, Apply!(brand: Self, signature: ('a, A: 'a) -> 'a): 'a) -> 'a)
550 where
551 Apply!(brand: F, signature: ('a, A: 'a) -> 'a): Clone,
552 Apply!(brand: Self, signature: ('a, A: 'a) -> 'a): Clone,
553 {
554 match ta {
555 Ok(fa) => F::map(|a| Ok(a), fa),
556 Err(e) => F::pure(Err(e)),
557 }
558 }
559}
560
561// ResultWithOkBrand<T> (Functor over E)
562
563impl_kind! {
564 impl<T: 'static> for ResultWithOkBrand<T> {
565 type Of<'a, A: 'a>: 'a = Result<T, A>;
566 }
567}
568
569impl<T: 'static> Functor for ResultWithOkBrand<T> {
570 /// Maps a function over the error value in the result.
571 ///
572 /// This method applies a function to the error value inside the result if it is `Err`, producing a new result with the transformed error. If the result is `Ok`, it is returned unchanged.
573 ///
574 /// ### Type Signature
575 ///
576 /// `forall a b t. Functor (Result' t) => (a -> b, Result t a) -> Result t b`
577 ///
578 /// ### Type Parameters
579 ///
580 /// * `F`: The type of the function to apply.
581 /// * `A`: The type of the error value inside the result.
582 /// * `B`: The type of the result of applying the function.
583 ///
584 /// ### Parameters
585 ///
586 /// * `f`: The function to apply to the error.
587 /// * `fa`: The result to map over.
588 ///
589 /// ### Returns
590 ///
591 /// A new result containing the mapped error, or the original success value.
592 ///
593 /// ### Examples
594 ///
595 /// ```
596 /// use fp_library::classes::functor::map;
597 /// use fp_library::brands::ResultWithOkBrand;
598 ///
599 /// assert_eq!(map::<ResultWithOkBrand<i32>, _, _, _>(|x: i32| x * 2, Err(5)), Err(10));
600 /// assert_eq!(map::<ResultWithOkBrand<i32>, _, _, _>(|x: i32| x * 2, Ok(1)), Ok(1));
601 /// ```
602 fn map<'a, F, A: 'a, B: 'a>(
603 f: F,
604 fa: Apply!(brand: Self, signature: ('a, A: 'a) -> 'a),
605 ) -> Apply!(brand: Self, signature: ('a, B: 'a) -> 'a)
606 where
607 F: Fn(A) -> B + 'a,
608 {
609 match fa {
610 Ok(t) => Ok(t),
611 Err(e) => Err(f(e)),
612 }
613 }
614}
615
616impl<T: Clone + 'static> Lift for ResultWithOkBrand<T> {
617 /// Lifts a binary function into the result context (over error).
618 ///
619 /// This method lifts a binary function to operate on error values within the result context.
620 ///
621 /// ### Type Signature
622 ///
623 /// `forall a b c t. Lift (Result' t) => ((a, b) -> c, Result t a, Result t b) -> Result t c`
624 ///
625 /// ### Type Parameters
626 ///
627 /// * `F`: The type of the binary function.
628 /// * `A`: The type of the first error value.
629 /// * `B`: The type of the second error value.
630 /// * `C`: The type of the result error value.
631 ///
632 /// ### Parameters
633 ///
634 /// * `f`: The binary function to apply to the errors.
635 /// * `fa`: The first result.
636 /// * `fb`: The second result.
637 ///
638 /// ### Returns
639 ///
640 /// `Err(f(a, b))` if both results are `Err`, otherwise the first success encountered.
641 ///
642 /// ### Examples
643 ///
644 /// ```
645 /// use fp_library::classes::lift::lift2;
646 /// use fp_library::brands::ResultWithOkBrand;
647 ///
648 /// assert_eq!(
649 /// lift2::<ResultWithOkBrand<i32>, _, _, _, _>(|x: i32, y: i32| x + y, Err(1), Err(2)),
650 /// Err(3)
651 /// );
652 /// assert_eq!(
653 /// lift2::<ResultWithOkBrand<i32>, _, _, _, _>(|x: i32, y: i32| x + y, Err(1), Ok(2)),
654 /// Ok(2)
655 /// );
656 /// assert_eq!(
657 /// lift2::<ResultWithOkBrand<i32>, _, _, _, _>(|x: i32, y: i32| x + y, Ok(1), Err(2)),
658 /// Ok(1)
659 /// );
660 /// assert_eq!(
661 /// lift2::<ResultWithOkBrand<i32>, _, _, _, _>(|x: i32, y: i32| x + y, Ok(1), Ok(2)),
662 /// Ok(1)
663 /// );
664 /// ```
665 fn lift2<'a, F, A, B, C>(
666 f: F,
667 fa: Apply!(brand: Self, signature: ('a, A: 'a) -> 'a),
668 fb: Apply!(brand: Self, signature: ('a, B: 'a) -> 'a),
669 ) -> Apply!(brand: Self, signature: ('a, C: 'a) -> 'a)
670 where
671 F: Fn(A, B) -> C + 'a,
672 A: Clone + 'a,
673 B: Clone + 'a,
674 C: 'a,
675 {
676 match (fa, fb) {
677 (Err(a), Err(b)) => Err(f(a, b)),
678 (Ok(t), _) => Ok(t),
679 (_, Ok(t)) => Ok(t),
680 }
681 }
682}
683
684impl<T: 'static> Pointed for ResultWithOkBrand<T> {
685 /// Wraps a value in a result (as error).
686 ///
687 /// This method wraps a value in the `Err` variant of a `Result`.
688 ///
689 /// ### Type Signature
690 ///
691 /// `forall a t. Pointed (Result' t) => a -> Result t a`
692 ///
693 /// ### Type Parameters
694 ///
695 /// * `A`: The type of the value to wrap.
696 ///
697 /// ### Parameters
698 ///
699 /// * `a`: The value to wrap.
700 ///
701 /// ### Returns
702 ///
703 /// `Err(a)`.
704 ///
705 /// ### Examples
706 ///
707 /// ```
708 /// use fp_library::classes::pointed::pure;
709 /// use fp_library::brands::ResultWithOkBrand;
710 ///
711 /// assert_eq!(pure::<ResultWithOkBrand<()>, _>(5), Err(5));
712 /// ```
713 fn pure<'a, A: 'a>(a: A) -> Apply!(brand: Self, signature: ('a, A: 'a) -> 'a) {
714 Err(a)
715 }
716}
717
718impl<T: Clone + 'static> ApplyFirst for ResultWithOkBrand<T> {}
719impl<T: Clone + 'static> ApplySecond for ResultWithOkBrand<T> {}
720
721impl<T: Clone + 'static> Semiapplicative for ResultWithOkBrand<T> {
722 /// Applies a wrapped function to a wrapped value (over error).
723 ///
724 /// This method applies a function wrapped in a result (as error) to a value wrapped in a result (as error).
725 ///
726 /// ### Type Signature
727 ///
728 /// `forall a b t. Semiapplicative (Result' t) => (Result t (a -> b), Result t a) -> Result t b`
729 ///
730 /// ### Type Parameters
731 ///
732 /// * `FnBrand`: The brand of the clonable function wrapper.
733 /// * `A`: The type of the input value.
734 /// * `B`: The type of the output value.
735 ///
736 /// ### Parameters
737 ///
738 /// * `ff`: The result containing the function (in Err).
739 /// * `fa`: The result containing the value (in Err).
740 ///
741 /// ### Returns
742 ///
743 /// `Err(f(a))` if both are `Err`, otherwise the first success encountered.
744 ///
745 /// ### Examples
746 ///
747 /// ```
748 /// use fp_library::classes::semiapplicative::apply;
749 /// use fp_library::classes::clonable_fn::ClonableFn;
750 /// use fp_library::brands::ResultWithOkBrand;
751 /// use fp_library::brands::RcFnBrand;
752 /// use std::rc::Rc;
753 ///
754 /// let f: Result<(), _> = Err(<RcFnBrand as ClonableFn>::new(|x: i32| x * 2));
755 /// assert_eq!(apply::<RcFnBrand, ResultWithOkBrand<()>, _, _>(f, Err(5)), Err(10));
756 /// let f: Result<i32, _> = Err(<RcFnBrand as ClonableFn>::new(|x: i32| x * 2));
757 /// assert_eq!(apply::<RcFnBrand, ResultWithOkBrand<i32>, _, _>(f, Ok(1)), Ok(1));
758 ///
759 /// let f_ok: Result<i32, Rc<dyn Fn(i32) -> i32>> = Ok(1);
760 /// assert_eq!(apply::<RcFnBrand, ResultWithOkBrand<i32>, _, _>(f_ok, Err(5)), Ok(1));
761 /// ```
762 fn apply<'a, FnBrand: 'a + ClonableFn, A: 'a + Clone, B: 'a>(
763 ff: Apply!(brand: Self, signature: ('a, Apply!(brand: FnBrand, kind: ClonableFn, lifetimes: ('a), types: (A, B)): 'a) -> 'a),
764 fa: Apply!(brand: Self, signature: ('a, A: 'a) -> 'a),
765 ) -> Apply!(brand: Self, signature: ('a, B: 'a) -> 'a) {
766 match (ff, fa) {
767 (Err(f), Err(a)) => Err(f(a)),
768 (Ok(t), _) => Ok(t),
769 (_, Ok(t)) => Ok(t),
770 }
771 }
772}
773
774impl<T: Clone + 'static> Semimonad for ResultWithOkBrand<T> {
775 /// Chains result computations (over error).
776 ///
777 /// This method chains two computations, where the second computation depends on the result of the first (over error).
778 ///
779 /// ### Type Signature
780 ///
781 /// `forall a b t. Semimonad (Result' t) => (Result t a, a -> Result t b) -> Result t b`
782 ///
783 /// ### Type Parameters
784 ///
785 /// * `F`: The type of the function to apply.
786 /// * `A`: The type of the result of the first computation.
787 /// * `B`: The type of the result of the second computation.
788 ///
789 /// ### Parameters
790 ///
791 /// * `ma`: The first result.
792 /// * `f`: The function to apply to the error value.
793 ///
794 /// ### Returns
795 ///
796 /// The result of applying `f` to the error if `ma` is `Err`, otherwise the original success.
797 ///
798 /// ### Examples
799 ///
800 /// ```
801 /// use fp_library::classes::semimonad::bind;
802 /// use fp_library::brands::ResultWithOkBrand;
803 ///
804 /// assert_eq!(
805 /// bind::<ResultWithOkBrand<()>, _, _, _>(Err(5), |x| Err(x * 2)),
806 /// Err(10)
807 /// );
808 /// assert_eq!(
809 /// bind::<ResultWithOkBrand<i32>, _, _, _>(Err(5), |_| Ok::<_, i32>(1)),
810 /// Ok(1)
811 /// );
812 /// assert_eq!(
813 /// bind::<ResultWithOkBrand<i32>, _, _, _>(Ok(1), |x: i32| Err(x * 2)),
814 /// Ok(1)
815 /// );
816 /// ```
817 fn bind<'a, F, A: 'a, B: 'a>(
818 ma: Apply!(brand: Self, signature: ('a, A: 'a) -> 'a),
819 f: F,
820 ) -> Apply!(brand: Self, signature: ('a, B: 'a) -> 'a)
821 where
822 F: Fn(A) -> Apply!(brand: Self, signature: ('a, B: 'a) -> 'a) + 'a,
823 {
824 match ma {
825 Ok(t) => Ok(t),
826 Err(e) => f(e),
827 }
828 }
829}
830
831impl<T: 'static> Foldable for ResultWithOkBrand<T> {
832 /// Folds the result from the right (over error).
833 ///
834 /// This method performs a right-associative fold of the result (over error).
835 ///
836 /// ### Type Signature
837 ///
838 /// `forall a b t. Foldable (Result' t) => ((a, b) -> b, b, Result t a) -> b`
839 ///
840 /// ### Type Parameters
841 ///
842 /// * `FnBrand`: The brand of the clonable function to use.
843 /// * `Func`: The type of the folding function.
844 /// * `A`: The type of the elements in the structure.
845 /// * `B`: The type of the accumulator.
846 ///
847 /// ### Parameters
848 ///
849 /// * `func`: The folding function.
850 /// * `initial`: The initial value.
851 /// * `fa`: The result to fold.
852 ///
853 /// ### Returns
854 ///
855 /// `func(a, initial)` if `fa` is `Err(a)`, otherwise `initial`.
856 ///
857 /// ### Examples
858 ///
859 /// ```
860 /// use fp_library::classes::foldable::fold_right;
861 /// use fp_library::brands::ResultWithOkBrand;
862 /// use fp_library::brands::RcFnBrand;
863 ///
864 /// assert_eq!(fold_right::<RcFnBrand, ResultWithOkBrand<i32>, _, _, _>(|x: i32, acc| x + acc, 0, Err(1)), 1);
865 /// assert_eq!(fold_right::<RcFnBrand, ResultWithOkBrand<()>, _, _, _>(|x: i32, acc| x + acc, 0, Ok(())), 0);
866 /// ```
867 fn fold_right<'a, FnBrand, F, A: 'a, B: 'a>(
868 func: F,
869 initial: B,
870 fa: Apply!(brand: Self, signature: ('a, A: 'a) -> 'a),
871 ) -> B
872 where
873 F: Fn(A, B) -> B + 'a,
874 FnBrand: ClonableFn + 'a,
875 {
876 match fa {
877 Err(e) => func(e, initial),
878 Ok(_) => initial,
879 }
880 }
881
882 /// Folds the result from the left (over error).
883 ///
884 /// This method performs a left-associative fold of the result (over error).
885 ///
886 /// ### Type Signature
887 ///
888 /// `forall a b t. Foldable (Result' t) => ((b, a) -> b, b, Result t a) -> b`
889 ///
890 /// ### Type Parameters
891 ///
892 /// * `FnBrand`: The brand of the clonable function to use.
893 /// * `Func`: The type of the folding function.
894 /// * `A`: The type of the elements in the structure.
895 /// * `B`: The type of the accumulator.
896 ///
897 /// ### Parameters
898 ///
899 /// * `func`: The folding function.
900 /// * `initial`: The initial value.
901 /// * `fa`: The result to fold.
902 ///
903 /// ### Returns
904 ///
905 /// `func(initial, a)` if `fa` is `Err(a)`, otherwise `initial`.
906 ///
907 /// ### Examples
908 ///
909 /// ```
910 /// use fp_library::classes::foldable::fold_left;
911 /// use fp_library::brands::ResultWithOkBrand;
912 /// use fp_library::brands::RcFnBrand;
913 ///
914 /// assert_eq!(fold_left::<RcFnBrand, ResultWithOkBrand<()>, _, _, _>(|acc, x: i32| acc + x, 0, Err(5)), 5);
915 /// assert_eq!(fold_left::<RcFnBrand, ResultWithOkBrand<i32>, _, _, _>(|acc, x: i32| acc + x, 0, Ok(1)), 0);
916 /// ```
917 fn fold_left<'a, FnBrand, F, A: 'a, B: 'a>(
918 func: F,
919 initial: B,
920 fa: Apply!(brand: Self, signature: ('a, A: 'a) -> 'a),
921 ) -> B
922 where
923 F: Fn(B, A) -> B + 'a,
924 FnBrand: ClonableFn + 'a,
925 {
926 match fa {
927 Err(e) => func(initial, e),
928 Ok(_) => initial,
929 }
930 }
931
932 /// Maps the value to a monoid and returns it (over error).
933 ///
934 /// This method maps the element of the result to a monoid and then returns it (over error).
935 ///
936 /// ### Type Signature
937 ///
938 /// `forall a m t. (Foldable (Result' t), Monoid m) => ((a) -> m, Result t a) -> m`
939 ///
940 /// ### Type Parameters
941 ///
942 /// * `FnBrand`: The brand of the clonable function to use.
943 /// * `Func`: The type of the mapping function.
944 /// * `A`: The type of the elements in the structure.
945 /// * `M`: The type of the monoid.
946 ///
947 /// ### Parameters
948 ///
949 /// * `func`: The mapping function.
950 /// * `fa`: The result to fold.
951 ///
952 /// ### Returns
953 ///
954 /// `func(a)` if `fa` is `Err(a)`, otherwise `M::empty()`.
955 ///
956 /// ### Examples
957 ///
958 /// ```
959 /// use fp_library::classes::foldable::fold_map;
960 /// use fp_library::brands::ResultWithOkBrand;
961 /// use fp_library::types::string;
962 /// use fp_library::brands::RcFnBrand;
963 ///
964 /// assert_eq!(
965 /// fold_map::<RcFnBrand, ResultWithOkBrand<()>, _, _, _>(|x: i32| x.to_string(), Err(5)),
966 /// "5".to_string()
967 /// );
968 /// assert_eq!(
969 /// fold_map::<RcFnBrand, ResultWithOkBrand<i32>, _, _, _>(|x: i32| x.to_string(), Ok(1)),
970 /// "".to_string()
971 /// );
972 /// ```
973 fn fold_map<'a, FnBrand, Func, A: 'a, M>(
974 func: Func,
975 fa: Apply!(brand: Self, signature: ('a, A: 'a) -> 'a),
976 ) -> M
977 where
978 M: Monoid + 'a,
979 Func: Fn(A) -> M + 'a,
980 FnBrand: ClonableFn + 'a,
981 {
982 match fa {
983 Err(e) => func(e),
984 Ok(_) => M::empty(),
985 }
986 }
987}
988
989impl<T: Clone + 'static> Traversable for ResultWithOkBrand<T> {
990 /// Traverses the result with an applicative function (over error).
991 ///
992 /// This method maps the element of the result to a computation, evaluates it, and combines the result into an applicative context (over error).
993 ///
994 /// ### Type Signature
995 ///
996 /// `forall a b f t. (Traversable (Result' t), Applicative f) => (a -> f b, Result t a) -> f (Result t b)`
997 ///
998 /// ### Type Parameters
999 ///
1000 /// * `F`: The applicative context.
1001 /// * `Func`: The type of the function to apply.
1002 /// * `A`: The type of the elements in the traversable structure.
1003 /// * `B`: The type of the elements in the resulting traversable structure.
1004 ///
1005 /// ### Parameters
1006 ///
1007 /// * `func`: The function to apply.
1008 /// * `ta`: The result to traverse.
1009 ///
1010 /// ### Returns
1011 ///
1012 /// The result wrapped in the applicative context.
1013 ///
1014 /// ### Examples
1015 ///
1016 /// ```
1017 /// use fp_library::classes::traversable::traverse;
1018 /// use fp_library::brands::{ResultWithOkBrand, OptionBrand};
1019 ///
1020 /// assert_eq!(
1021 /// traverse::<ResultWithOkBrand<()>, OptionBrand, _, _, _>(|x| Some(x * 2), Err(5)),
1022 /// Some(Err(10))
1023 /// );
1024 /// assert_eq!(
1025 /// traverse::<ResultWithOkBrand<i32>, OptionBrand, _, _, _>(|x: i32| Some(x * 2), Ok(1)),
1026 /// Some(Ok(1))
1027 /// );
1028 /// assert_eq!(
1029 /// traverse::<ResultWithOkBrand<()>, OptionBrand, _, _, _>(|_| None::<i32>, Err(5)),
1030 /// None
1031 /// );
1032 /// ```
1033 fn traverse<'a, F: Applicative, Func, A: 'a + Clone, B: 'a + Clone>(
1034 func: Func,
1035 ta: Apply!(brand: Self, signature: ('a, A: 'a) -> 'a),
1036 ) -> Apply!(brand: F, signature: ('a, Apply!(brand: Self, signature: ('a, B: 'a) -> 'a): 'a) -> 'a)
1037 where
1038 Func: Fn(A) -> Apply!(brand: F, signature: ('a, B: 'a) -> 'a) + 'a,
1039 Apply!(brand: Self, signature: ('a, B: 'a) -> 'a): Clone,
1040 {
1041 match ta {
1042 Err(e) => F::map(|b| Err(b), func(e)),
1043 Ok(t) => F::pure(Ok(t)),
1044 }
1045 }
1046
1047 /// Sequences a result of applicative (over error).
1048 ///
1049 /// This method evaluates the computation inside the result and accumulates the result into an applicative context (over error).
1050 ///
1051 /// ### Type Signature
1052 ///
1053 /// `forall a f t. (Traversable (Result' t), Applicative f) => (Result t (f a)) -> f (Result t a)`
1054 ///
1055 /// ### Type Parameters
1056 ///
1057 /// * `F`: The applicative context.
1058 /// * `A`: The type of the elements in the traversable structure.
1059 ///
1060 /// ### Parameters
1061 ///
1062 /// * `ta`: The result containing the applicative value.
1063 ///
1064 /// ### Returns
1065 ///
1066 /// The result wrapped in the applicative context.
1067 ///
1068 /// ### Examples
1069 ///
1070 /// ```
1071 /// use fp_library::classes::traversable::sequence;
1072 /// use fp_library::brands::{ResultWithOkBrand, OptionBrand};
1073 ///
1074 /// assert_eq!(
1075 /// sequence::<ResultWithOkBrand<()>, OptionBrand, _>(Err(Some(5))),
1076 /// Some(Err(5))
1077 /// );
1078 /// assert_eq!(
1079 /// sequence::<ResultWithOkBrand<i32>, OptionBrand, i32>(Ok::<_, Option<i32>>(1)),
1080 /// Some(Ok::<i32, i32>(1))
1081 /// );
1082 /// assert_eq!(
1083 /// sequence::<ResultWithOkBrand<()>, OptionBrand, _>(Err(None::<i32>)),
1084 /// None
1085 /// );
1086 /// ```
1087 fn sequence<'a, F: Applicative, A: 'a + Clone>(
1088 ta: Apply!(brand: Self, signature: ('a, Apply!(brand: F, signature: ('a, A: 'a) -> 'a): 'a) -> 'a)
1089 ) -> Apply!(brand: F, signature: ('a, Apply!(brand: Self, signature: ('a, A: 'a) -> 'a): 'a) -> 'a)
1090 where
1091 Apply!(brand: F, signature: ('a, A: 'a) -> 'a): Clone,
1092 Apply!(brand: Self, signature: ('a, A: 'a) -> 'a): Clone,
1093 {
1094 match ta {
1095 Err(fe) => F::map(|e| Err(e), fe),
1096 Ok(t) => F::pure(Ok(t)),
1097 }
1098 }
1099}
1100
1101impl<E: 'static, FnBrand: SendClonableFn> ParFoldable<FnBrand> for ResultWithErrBrand<E> {
1102 /// Maps the value to a monoid and returns it, or returns empty, in parallel.
1103 ///
1104 /// This method maps the element of the result to a monoid and then returns it. The mapping operation may be executed in parallel.
1105 ///
1106 /// ### Type Signature
1107 ///
1108 /// `forall a m e. (ParFoldable (Result e), Monoid m, Send m, Sync m) => (f a m, Result e a) -> m`
1109 ///
1110 /// ### Type Parameters
1111 ///
1112 /// * `FnBrand`: The brand of thread-safe function to use (must implement `SendClonableFn`).
1113 /// * `A`: The element type (must be `Send + Sync`).
1114 /// * `M`: The monoid type (must be `Send + Sync`).
1115 ///
1116 /// ### Parameters
1117 ///
1118 /// * `func`: The thread-safe function to map each element to a monoid.
1119 /// * `fa`: The result to fold.
1120 ///
1121 /// ### Examples
1122 ///
1123 /// ```
1124 /// use fp_library::classes::par_foldable::par_fold_map;
1125 /// use fp_library::brands::{ResultWithErrBrand, ArcFnBrand};
1126 /// use fp_library::classes::send_clonable_fn::SendClonableFn;
1127 /// use fp_library::types::string;
1128 ///
1129 /// let x: Result<i32, ()> = Ok(5);
1130 /// let f = <ArcFnBrand as SendClonableFn>::new_send(|x: i32| x.to_string());
1131 /// assert_eq!(par_fold_map::<ArcFnBrand, ResultWithErrBrand<()>, _, _>(f.clone(), x), "5".to_string());
1132 ///
1133 /// let x_err: Result<i32, i32> = Err(1);
1134 /// assert_eq!(par_fold_map::<ArcFnBrand, ResultWithErrBrand<i32>, _, _>(f, x_err), "".to_string());
1135 /// ```
1136 fn par_fold_map<'a, A, M>(
1137 func: Apply!(brand: FnBrand, kind: SendClonableFn, output: SendOf, lifetimes: ('a), types: (A, M)),
1138 fa: Apply!(brand: Self, signature: ('a, A: 'a) -> 'a),
1139 ) -> M
1140 where
1141 A: 'a + Clone + Send + Sync,
1142 M: Monoid + Send + Sync + 'a,
1143 {
1144 match fa {
1145 Ok(a) => func(a),
1146 Err(_) => M::empty(),
1147 }
1148 }
1149
1150 /// Folds the result from the right in parallel.
1151 ///
1152 /// This method folds the result by applying a function from right to left, potentially in parallel.
1153 ///
1154 /// ### Type Signature
1155 ///
1156 /// `forall a b e. ParFoldable (Result e) => (f (a, b) b, b, Result e a) -> b`
1157 ///
1158 /// ### Type Parameters
1159 ///
1160 /// * `FnBrand`: The brand of thread-safe function to use.
1161 /// * `A`: The element type (must be `Send + Sync`).
1162 /// * `B`: The accumulator type (must be `Send + Sync`).
1163 ///
1164 /// ### Parameters
1165 ///
1166 /// * `f`: The thread-safe function to apply to each element and the accumulator.
1167 /// * `init`: The initial value.
1168 /// * `fa`: The result to fold.
1169 ///
1170 /// ### Examples
1171 ///
1172 /// ```
1173 /// use fp_library::classes::par_foldable::par_fold_right;
1174 /// use fp_library::brands::{ResultWithErrBrand, ArcFnBrand};
1175 /// use fp_library::classes::send_clonable_fn::SendClonableFn;
1176 ///
1177 /// let x: Result<i32, ()> = Ok(5);
1178 /// let f = <ArcFnBrand as SendClonableFn>::new_send(|(a, b): (i32, i32)| a + b);
1179 /// assert_eq!(par_fold_right::<ArcFnBrand, ResultWithErrBrand<()>, _, _>(f.clone(), 10, x), 15);
1180 ///
1181 /// let x_err: Result<i32, i32> = Err(1);
1182 /// assert_eq!(par_fold_right::<ArcFnBrand, ResultWithErrBrand<i32>, _, _>(f, 10, x_err), 10);
1183 fn par_fold_right<'a, A, B>(
1184 func: Apply!(brand: FnBrand, kind: SendClonableFn, output: SendOf, lifetimes: ('a), types: ((A, B), B)),
1185 initial: B,
1186 fa: Apply!(brand: Self, signature: ('a, A: 'a) -> 'a),
1187 ) -> B
1188 where
1189 A: 'a + Clone + Send + Sync,
1190 B: Send + Sync + 'a,
1191 {
1192 match fa {
1193 Ok(a) => func((a, initial)),
1194 Err(_) => initial,
1195 }
1196 }
1197}
1198
1199impl<T: 'static, FnBrand: SendClonableFn> ParFoldable<FnBrand> for ResultWithOkBrand<T> {
1200 /// Maps the value to a monoid and returns it, or returns empty, in parallel (over error).
1201 ///
1202 /// This method maps the element of the result to a monoid and then returns it (over error). The mapping operation may be executed in parallel.
1203 ///
1204 /// ### Type Signature
1205 ///
1206 /// `forall a m t. (ParFoldable (Result' t), Monoid m, Send m, Sync m) => (f a m, Result t a) -> m`
1207 ///
1208 /// ### Type Parameters
1209 ///
1210 /// * `FnBrand`: The brand of thread-safe function to use (must implement `SendClonableFn`).
1211 /// * `A`: The element type (must be `Send + Sync`).
1212 /// * `M`: The monoid type (must be `Send + Sync`).
1213 ///
1214 /// ### Parameters
1215 ///
1216 /// * `func`: The thread-safe function to map each element to a monoid.
1217 /// * `fa`: The result to fold.
1218 ///
1219 /// ### Examples
1220 ///
1221 /// ```
1222 /// use fp_library::classes::par_foldable::par_fold_map;
1223 /// use fp_library::brands::{ResultWithOkBrand, ArcFnBrand};
1224 /// use fp_library::classes::send_clonable_fn::SendClonableFn;
1225 /// use fp_library::types::string;
1226 ///
1227 /// let x: Result<(), i32> = Err(5);
1228 /// let f = <ArcFnBrand as SendClonableFn>::new_send(|x: i32| x.to_string());
1229 /// assert_eq!(par_fold_map::<ArcFnBrand, ResultWithOkBrand<()>, _, _>(f.clone(), x), "5".to_string());
1230 ///
1231 /// let x_ok: Result<i32, i32> = Ok(1);
1232 /// assert_eq!(par_fold_map::<ArcFnBrand, ResultWithOkBrand<i32>, _, _>(f, x_ok), "".to_string());
1233 /// ```
1234 fn par_fold_map<'a, A, M>(
1235 func: Apply!(brand: FnBrand, kind: SendClonableFn, output: SendOf, lifetimes: ('a), types: (A, M)),
1236 fa: Apply!(brand: Self, signature: ('a, A: 'a) -> 'a),
1237 ) -> M
1238 where
1239 A: 'a + Clone + Send + Sync,
1240 M: Monoid + Send + Sync + 'a,
1241 {
1242 match fa {
1243 Err(e) => func(e),
1244 Ok(_) => M::empty(),
1245 }
1246 }
1247
1248 /// Folds the result from the right in parallel (over error).
1249 ///
1250 /// This method folds the result by applying a function from right to left, potentially in parallel (over error).
1251 ///
1252 /// ### Type Signature
1253 ///
1254 /// `forall a b t. ParFoldable (Result' t) => (f (a, b) b, b, Result t a) -> b`
1255 ///
1256 /// ### Type Parameters
1257 ///
1258 /// * `FnBrand`: The brand of thread-safe function to use.
1259 /// * `A`: The element type (must be `Send + Sync`).
1260 /// * `B`: The accumulator type (must be `Send + Sync`).
1261 ///
1262 /// ### Parameters
1263 ///
1264 /// * `f`: The thread-safe function to apply to each element and the accumulator.
1265 /// * `init`: The initial value.
1266 /// * `fa`: The result to fold.
1267 ///
1268 /// ### Examples
1269 ///
1270 /// ```
1271 /// use fp_library::classes::par_foldable::par_fold_right;
1272 /// use fp_library::brands::{ResultWithOkBrand, ArcFnBrand};
1273 /// use fp_library::classes::send_clonable_fn::SendClonableFn;
1274 ///
1275 /// let x: Result<(), i32> = Err(5);
1276 /// let f = <ArcFnBrand as SendClonableFn>::new_send(|(a, b): (i32, i32)| a + b);
1277 /// assert_eq!(par_fold_right::<ArcFnBrand, ResultWithOkBrand<()>, _, _>(f.clone(), 10, x), 15);
1278 ///
1279 /// let x_ok: Result<i32, i32> = Ok(1);
1280 /// assert_eq!(par_fold_right::<ArcFnBrand, ResultWithOkBrand<i32>, _, _>(f, 10, x_ok), 10);
1281 fn par_fold_right<'a, A, B>(
1282 func: Apply!(brand: FnBrand, kind: SendClonableFn, output: SendOf, lifetimes: ('a), types: ((A, B), B)),
1283 initial: B,
1284 fa: Apply!(brand: Self, signature: ('a, A: 'a) -> 'a),
1285 ) -> B
1286 where
1287 A: 'a + Clone + Send + Sync,
1288 B: Send + Sync + 'a,
1289 {
1290 match fa {
1291 Err(e) => func((e, initial)),
1292 Ok(_) => initial,
1293 }
1294 }
1295}
1296
1297#[cfg(test)]
1298mod tests {
1299 use super::*;
1300 use crate::{
1301 brands::{ArcFnBrand, OptionBrand, RcFnBrand},
1302 classes::{
1303 functor::map,
1304 par_foldable::{par_fold_map, par_fold_right},
1305 pointed::pure,
1306 semiapplicative::apply,
1307 semimonad::bind,
1308 send_clonable_fn::new_send,
1309 },
1310 functions::{compose, identity},
1311 };
1312 use quickcheck_macros::quickcheck;
1313
1314 // Functor Laws
1315
1316 /// Tests the identity law for Functor.
1317 #[quickcheck]
1318 fn functor_identity(x: Result<i32, i32>) -> bool {
1319 map::<ResultWithErrBrand<i32>, _, _, _>(identity, x) == x
1320 }
1321
1322 /// Tests the composition law for Functor.
1323 #[quickcheck]
1324 fn functor_composition(x: Result<i32, i32>) -> bool {
1325 let f = |x: i32| x.wrapping_add(1);
1326 let g = |x: i32| x.wrapping_mul(2);
1327 map::<ResultWithErrBrand<i32>, _, _, _>(compose(f, g), x)
1328 == map::<ResultWithErrBrand<i32>, _, _, _>(
1329 f,
1330 map::<ResultWithErrBrand<i32>, _, _, _>(g, x),
1331 )
1332 }
1333
1334 // Applicative Laws
1335
1336 /// Tests the identity law for Applicative.
1337 #[quickcheck]
1338 fn applicative_identity(v: Result<i32, i32>) -> bool {
1339 apply::<RcFnBrand, ResultWithErrBrand<i32>, _, _>(
1340 pure::<ResultWithErrBrand<i32>, _>(<RcFnBrand as ClonableFn>::new(identity)),
1341 v,
1342 ) == v
1343 }
1344
1345 /// Tests the homomorphism law for Applicative.
1346 #[quickcheck]
1347 fn applicative_homomorphism(x: i32) -> bool {
1348 let f = |x: i32| x.wrapping_mul(2);
1349 apply::<RcFnBrand, ResultWithErrBrand<i32>, _, _>(
1350 pure::<ResultWithErrBrand<i32>, _>(<RcFnBrand as ClonableFn>::new(f)),
1351 pure::<ResultWithErrBrand<i32>, _>(x),
1352 ) == pure::<ResultWithErrBrand<i32>, _>(f(x))
1353 }
1354
1355 /// Tests the composition law for Applicative.
1356 #[quickcheck]
1357 fn applicative_composition(
1358 w: Result<i32, i32>,
1359 u_is_ok: bool,
1360 v_is_ok: bool,
1361 ) -> bool {
1362 let v_fn = |x: i32| x.wrapping_mul(2);
1363 let u_fn = |x: i32| x.wrapping_add(1);
1364
1365 let v = if v_is_ok {
1366 pure::<ResultWithErrBrand<i32>, _>(<RcFnBrand as ClonableFn>::new(v_fn))
1367 } else {
1368 Err(100)
1369 };
1370 let u = if u_is_ok {
1371 pure::<ResultWithErrBrand<i32>, _>(<RcFnBrand as ClonableFn>::new(u_fn))
1372 } else {
1373 Err(200)
1374 };
1375
1376 // RHS: u <*> (v <*> w)
1377 let vw = apply::<RcFnBrand, ResultWithErrBrand<i32>, _, _>(v.clone(), w.clone());
1378 let rhs = apply::<RcFnBrand, ResultWithErrBrand<i32>, _, _>(u.clone(), vw);
1379
1380 // LHS: pure(compose) <*> u <*> v <*> w
1381 // equivalent to (u . v) <*> w
1382 let uv = match (u, v) {
1383 (Ok(uf), Ok(vf)) => {
1384 let composed = move |x| uf(vf(x));
1385 Ok(<RcFnBrand as ClonableFn>::new(composed))
1386 }
1387 (Err(e), _) => Err(e),
1388 (_, Err(e)) => Err(e),
1389 };
1390
1391 let lhs = apply::<RcFnBrand, ResultWithErrBrand<i32>, _, _>(uv, w);
1392
1393 lhs == rhs
1394 }
1395
1396 /// Tests the interchange law for Applicative.
1397 #[quickcheck]
1398 fn applicative_interchange(y: i32) -> bool {
1399 // u <*> pure y = pure ($ y) <*> u
1400 let f = |x: i32| x.wrapping_mul(2);
1401 let u = pure::<ResultWithErrBrand<i32>, _>(<RcFnBrand as ClonableFn>::new(f));
1402
1403 let lhs = apply::<RcFnBrand, ResultWithErrBrand<i32>, _, _>(
1404 u.clone(),
1405 pure::<ResultWithErrBrand<i32>, _>(y),
1406 );
1407
1408 let rhs_fn = <RcFnBrand as ClonableFn>::new(move |f: std::rc::Rc<dyn Fn(i32) -> i32>| f(y));
1409 let rhs = apply::<RcFnBrand, ResultWithErrBrand<i32>, _, _>(
1410 pure::<ResultWithErrBrand<i32>, _>(rhs_fn),
1411 u,
1412 );
1413
1414 lhs == rhs
1415 }
1416
1417 // Monad Laws
1418
1419 /// Tests the left identity law for Monad.
1420 #[quickcheck]
1421 fn monad_left_identity(a: i32) -> bool {
1422 let f = |x: i32| -> Result<i32, i32> { Err(x.wrapping_mul(2)) };
1423 bind::<ResultWithErrBrand<i32>, _, _, _>(pure::<ResultWithErrBrand<i32>, _>(a), f) == f(a)
1424 }
1425
1426 /// Tests the right identity law for Monad.
1427 #[quickcheck]
1428 fn monad_right_identity(m: Result<i32, i32>) -> bool {
1429 bind::<ResultWithErrBrand<i32>, _, _, _>(m, pure::<ResultWithErrBrand<i32>, _>) == m
1430 }
1431
1432 /// Tests the associativity law for Monad.
1433 #[quickcheck]
1434 fn monad_associativity(m: Result<i32, i32>) -> bool {
1435 let f = |x: i32| -> Result<i32, i32> { Err(x.wrapping_mul(2)) };
1436 let g = |x: i32| -> Result<i32, i32> { Err(x.wrapping_add(1)) };
1437 bind::<ResultWithErrBrand<i32>, _, _, _>(bind::<ResultWithErrBrand<i32>, _, _, _>(m, f), g)
1438 == bind::<ResultWithErrBrand<i32>, _, _, _>(m, |x| {
1439 bind::<ResultWithErrBrand<i32>, _, _, _>(f(x), g)
1440 })
1441 }
1442
1443 // Edge Cases
1444
1445 /// Tests `map` on `Err`.
1446 #[test]
1447 fn map_err() {
1448 assert_eq!(
1449 map::<ResultWithErrBrand<i32>, _, _, _>(|x: i32| x + 1, Err::<i32, i32>(1)),
1450 Err(1)
1451 );
1452 }
1453
1454 /// Tests `bind` on `Err`.
1455 #[test]
1456 fn bind_err() {
1457 assert_eq!(
1458 bind::<ResultWithErrBrand<i32>, _, _, _>(Err::<i32, i32>(1), |x: i32| Ok(x + 1)),
1459 Err(1)
1460 );
1461 }
1462
1463 /// Tests `bind` returning `Err`.
1464 #[test]
1465 fn bind_returning_err() {
1466 assert_eq!(bind::<ResultWithErrBrand<i32>, _, _, _>(Ok(1), |_| Err::<i32, i32>(2)), Err(2));
1467 }
1468
1469 /// Tests `fold_right` on `Err`.
1470 #[test]
1471 fn fold_right_err() {
1472 assert_eq!(
1473 crate::classes::foldable::fold_right::<RcFnBrand, ResultWithErrBrand<i32>, _, _, _>(
1474 |x: i32, acc| x + acc,
1475 0,
1476 Err(1)
1477 ),
1478 0
1479 );
1480 }
1481
1482 /// Tests `fold_left` on `Err`.
1483 #[test]
1484 fn fold_left_err() {
1485 assert_eq!(
1486 crate::classes::foldable::fold_left::<RcFnBrand, ResultWithErrBrand<i32>, _, _, _>(
1487 |acc, x: i32| acc + x,
1488 0,
1489 Err(1)
1490 ),
1491 0
1492 );
1493 }
1494
1495 /// Tests `traverse` on `Err`.
1496 #[test]
1497 fn traverse_err() {
1498 assert_eq!(
1499 crate::classes::traversable::traverse::<ResultWithErrBrand<i32>, OptionBrand, _, _, _>(
1500 |x: i32| Some(x + 1),
1501 Err(1)
1502 ),
1503 Some(Err(1))
1504 );
1505 }
1506
1507 /// Tests `traverse` returning `Err`.
1508 #[test]
1509 fn traverse_returning_err() {
1510 assert_eq!(
1511 crate::classes::traversable::traverse::<ResultWithErrBrand<i32>, OptionBrand, _, _, _>(
1512 |_: i32| None::<i32>,
1513 Ok(1)
1514 ),
1515 None
1516 );
1517 }
1518
1519 // ParFoldable Tests for ResultWithErrBrand
1520
1521 /// Tests `par_fold_map` on `Ok`.
1522 #[test]
1523 fn par_fold_map_ok() {
1524 let x: Result<i32, ()> = Ok(5);
1525 let f = new_send::<ArcFnBrand, _, _>(|x: i32| x.to_string());
1526 assert_eq!(par_fold_map::<ArcFnBrand, ResultWithErrBrand<()>, _, _>(f, x), "5".to_string());
1527 }
1528
1529 /// Tests `par_fold_map` on `Err`.
1530 #[test]
1531 fn par_fold_map_err_val() {
1532 let x: Result<i32, i32> = Err(5);
1533 let f = new_send::<ArcFnBrand, _, _>(|x: i32| x.to_string());
1534 assert_eq!(par_fold_map::<ArcFnBrand, ResultWithErrBrand<i32>, _, _>(f, x), "".to_string());
1535 }
1536
1537 /// Tests `par_fold_right` on `Ok`.
1538 #[test]
1539 fn par_fold_right_ok() {
1540 let x: Result<i32, ()> = Ok(5);
1541 let f = new_send::<ArcFnBrand, _, _>(|(a, b): (i32, i32)| a + b);
1542 assert_eq!(par_fold_right::<ArcFnBrand, ResultWithErrBrand<()>, _, _>(f, 10, x), 15);
1543 }
1544
1545 /// Tests `par_fold_right` on `Err`.
1546 #[test]
1547 fn par_fold_right_err_val() {
1548 let x: Result<i32, i32> = Err(5);
1549 let f = new_send::<ArcFnBrand, _, _>(|(a, b): (i32, i32)| a + b);
1550 assert_eq!(par_fold_right::<ArcFnBrand, ResultWithErrBrand<i32>, _, _>(f, 10, x), 10);
1551 }
1552
1553 // ParFoldable Tests for ResultWithOkBrand
1554
1555 /// Tests `par_fold_map` on `Err` (which holds the value for ResultWithOkBrand).
1556 #[test]
1557 fn par_fold_map_err_ok_brand() {
1558 let x: Result<(), i32> = Err(5);
1559 let f = new_send::<ArcFnBrand, _, _>(|x: i32| x.to_string());
1560 assert_eq!(par_fold_map::<ArcFnBrand, ResultWithOkBrand<()>, _, _>(f, x), "5".to_string());
1561 }
1562
1563 /// Tests `par_fold_map` on `Ok` (which is empty for ResultWithOkBrand).
1564 #[test]
1565 fn par_fold_map_ok_ok_brand() {
1566 let x: Result<i32, i32> = Ok(5);
1567 let f = new_send::<ArcFnBrand, _, _>(|x: i32| x.to_string());
1568 assert_eq!(par_fold_map::<ArcFnBrand, ResultWithOkBrand<i32>, _, _>(f, x), "".to_string());
1569 }
1570
1571 /// Tests `par_fold_right` on `Err` (which holds the value for ResultWithOkBrand).
1572 #[test]
1573 fn par_fold_right_err_ok_brand() {
1574 let x: Result<(), i32> = Err(5);
1575 let f = new_send::<ArcFnBrand, _, _>(|(a, b): (i32, i32)| a + b);
1576 assert_eq!(par_fold_right::<ArcFnBrand, ResultWithOkBrand<()>, _, _>(f, 10, x), 15);
1577 }
1578
1579 /// Tests `par_fold_right` on `Ok` (which is empty for ResultWithOkBrand).
1580 #[test]
1581 fn par_fold_right_ok_ok_brand() {
1582 let x: Result<i32, i32> = Ok(5);
1583 let f = new_send::<ArcFnBrand, _, _>(|(a, b): (i32, i32)| a + b);
1584 assert_eq!(par_fold_right::<ArcFnBrand, ResultWithOkBrand<i32>, _, _>(f, 10, x), 10);
1585 }
1586}