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}