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