Skip to main content

fp_library/types/
option.rs

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