fp_library/types/
result.rs

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