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