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			dispatch::Ref,
13			impl_kind,
14			kinds::*,
15		},
16		core::ops::ControlFlow,
17		fp_macros::*,
18	};
19
20	impl_kind! {
21		for OptionBrand {
22			type Of<'a, A: 'a>: 'a = Option<A>;
23		}
24	}
25
26	impl Functor for OptionBrand {
27		/// Maps a function over the value in the option.
28		///
29		/// 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`.
30		#[document_signature]
31		///
32		#[document_type_parameters(
33			"The lifetime of the value.",
34			"The type of the value inside the option.",
35			"The type of the result of applying the function."
36		)]
37		///
38		#[document_parameters("The function to apply to the value.", "The option to map over.")]
39		///
40		#[document_returns(
41			"A new option containing the result of applying the function, or `None`."
42		)]
43		///
44		#[document_examples]
45		///
46		/// ```
47		/// use fp_library::{
48		/// 	brands::*,
49		/// 	functions::*,
50		/// };
51		///
52		/// let x = Some(5);
53		/// let y = explicit::map::<OptionBrand, _, _, _, _>(|i| i * 2, x);
54		/// assert_eq!(y, Some(10));
55		/// ```
56		fn map<'a, A: 'a, B: 'a>(
57			func: impl Fn(A) -> B + 'a,
58			fa: Apply!(<Self as Kind!( type Of<'a, T: 'a>: 'a; )>::Of<'a, A>),
59		) -> Apply!(<Self as Kind!( type Of<'a, T: 'a>: 'a; )>::Of<'a, B>) {
60			fa.map(func)
61		}
62	}
63
64	impl Lift for OptionBrand {
65		/// Lifts a binary function into the option context.
66		///
67		/// This method lifts a binary function to operate on values within the option context.
68		#[document_signature]
69		///
70		#[document_type_parameters(
71			"The lifetime of the values.",
72			"The type of the first option's value.",
73			"The type of the second option's value.",
74			"The return type of the function."
75		)]
76		///
77		#[document_parameters(
78			"The binary function to apply.",
79			"The first option.",
80			"The second option."
81		)]
82		///
83		#[document_returns("`Some(f(a, b))` if both options are `Some`, otherwise `None`.")]
84		#[document_examples]
85		///
86		/// ```
87		/// use fp_library::{
88		/// 	brands::*,
89		/// 	functions::*,
90		/// };
91		///
92		/// let x = Some(1);
93		/// let y = Some(2);
94		/// let z = explicit::lift2::<OptionBrand, _, _, _, _, _, _>(|a, b| a + b, x, y);
95		/// assert_eq!(z, Some(3));
96		/// ```
97		fn lift2<'a, A, B, C>(
98			func: impl Fn(A, B) -> C + 'a,
99			fa: Apply!(<Self as Kind!( type Of<'a, T: 'a>: 'a; )>::Of<'a, A>),
100			fb: Apply!(<Self as Kind!( type Of<'a, T: 'a>: 'a; )>::Of<'a, B>),
101		) -> Apply!(<Self as Kind!( type Of<'a, T: 'a>: 'a; )>::Of<'a, C>)
102		where
103			A: 'a,
104			B: 'a,
105			C: 'a, {
106			fa.zip(fb).map(|(a, b)| func(a, b))
107		}
108	}
109
110	impl Pointed for OptionBrand {
111		/// Wraps a value in an option.
112		///
113		/// This method wraps a value in an option context.
114		#[document_signature]
115		///
116		#[document_type_parameters("The lifetime of the value.", "The type of the value to wrap.")]
117		///
118		#[document_parameters("The value to wrap.")]
119		///
120		#[document_returns("`Some(a)`.")]
121		///
122		#[document_examples]
123		///
124		/// ```
125		/// use fp_library::{
126		/// 	brands::OptionBrand,
127		/// 	functions::*,
128		/// };
129		///
130		/// let x = pure::<OptionBrand, _>(5);
131		/// assert_eq!(x, Some(5));
132		/// ```
133		fn pure<'a, A: 'a>(a: A) -> Apply!(<Self as Kind!( type Of<'a, T: 'a>: 'a; )>::Of<'a, A>) {
134			Some(a)
135		}
136	}
137
138	impl ApplyFirst for OptionBrand {}
139	impl ApplySecond for OptionBrand {}
140
141	impl Semiapplicative for OptionBrand {
142		/// Applies a wrapped function to a wrapped value.
143		///
144		/// This method applies a function wrapped in an option to a value wrapped in an option.
145		#[document_signature]
146		///
147		#[document_type_parameters(
148			"The lifetime of the values.",
149			"The brand of the cloneable function wrapper.",
150			"The type of the input value.",
151			"The type of the output value."
152		)]
153		///
154		#[document_parameters(
155			"The option containing the function.",
156			"The option containing the value."
157		)]
158		///
159		#[document_returns("`Some(f(a))` if both are `Some`, otherwise `None`.")]
160		#[document_examples]
161		///
162		/// ```
163		/// use fp_library::{
164		/// 	brands::*,
165		/// 	classes::*,
166		/// 	functions::*,
167		/// };
168		///
169		/// let f = Some(lift_fn_new::<RcFnBrand, _, _>(|x: i32| x * 2));
170		/// let x = Some(5);
171		/// let y = apply::<RcFnBrand, OptionBrand, _, _>(f, x);
172		/// assert_eq!(y, Some(10));
173		/// ```
174		fn apply<'a, FnBrand: 'a + CloneFn, A: 'a + Clone, B: 'a>(
175			ff: Apply!(<Self as Kind!( type Of<'a, T: 'a>: 'a; )>::Of<'a, <FnBrand as CloneFn>::Of<'a, A, B>>),
176			fa: Apply!(<Self as Kind!( type Of<'a, T: 'a>: 'a; )>::Of<'a, A>),
177		) -> Apply!(<Self as Kind!( type Of<'a, T: 'a>: 'a; )>::Of<'a, B>) {
178			match (ff, fa) {
179				(Some(f), Some(a)) => Some(f(a)),
180				_ => None,
181			}
182		}
183	}
184
185	impl Semimonad for OptionBrand {
186		/// Chains option computations.
187		///
188		/// This method chains two option computations, where the second computation depends on the result of the first.
189		#[document_signature]
190		///
191		#[document_type_parameters(
192			"The lifetime of the values.",
193			"The type of the result of the first computation.",
194			"The type of the result of the second computation."
195		)]
196		///
197		#[document_parameters(
198			"The first option.",
199			"The function to apply to the value inside the option."
200		)]
201		///
202		#[document_returns(
203			"The result of applying `f` to the value if `ma` is `Some`, otherwise `None`."
204		)]
205		#[document_examples]
206		///
207		/// ```
208		/// use fp_library::{
209		/// 	brands::OptionBrand,
210		/// 	functions::*,
211		/// };
212		///
213		/// let x = Some(5);
214		/// let y = explicit::bind::<OptionBrand, _, _, _, _>(x, |i| Some(i * 2));
215		/// assert_eq!(y, Some(10));
216		/// ```
217		fn bind<'a, A: 'a, B: 'a>(
218			ma: Apply!(<Self as Kind!( type Of<'a, T: 'a>: 'a; )>::Of<'a, A>),
219			func: impl Fn(A) -> Apply!(<Self as Kind!( type Of<'a, T: 'a>: 'a; )>::Of<'a, B>) + 'a,
220		) -> Apply!(<Self as Kind!( type Of<'a, T: 'a>: 'a; )>::Of<'a, B>) {
221			ma.and_then(func)
222		}
223	}
224
225	impl Alt for OptionBrand {
226		/// Chooses between two options.
227		///
228		/// Returns the first `Some` value, or `None` if both are `None`.
229		#[document_signature]
230		///
231		#[document_type_parameters("The lifetime of the values.", "The type of the value.")]
232		///
233		#[document_parameters("The first option.", "The second option.")]
234		///
235		#[document_returns("The first `Some` value, or `None`.")]
236		#[document_examples]
237		///
238		/// ```
239		/// use fp_library::{
240		/// 	brands::*,
241		/// 	classes::*,
242		/// 	functions::*,
243		/// };
244		///
245		/// assert_eq!(explicit::alt::<OptionBrand, _, _, _>(None, Some(5)), Some(5));
246		/// assert_eq!(explicit::alt::<OptionBrand, _, _, _>(Some(3), Some(5)), Some(3));
247		/// assert_eq!(explicit::alt::<OptionBrand, _, _, _>(None::<i32>, None), None);
248		/// ```
249		fn alt<'a, A: 'a>(
250			fa1: Apply!(<Self as Kind!( type Of<'a, T: 'a>: 'a; )>::Of<'a, A>),
251			fa2: Apply!(<Self as Kind!( type Of<'a, T: 'a>: 'a; )>::Of<'a, A>),
252		) -> Apply!(<Self as Kind!( type Of<'a, T: 'a>: 'a; )>::Of<'a, A>) {
253			fa1.or(fa2)
254		}
255	}
256
257	impl RefAlt for OptionBrand {
258		/// Chooses between two options by reference.
259		///
260		/// Returns the first `Some` value (cloned), or `None` if both are `None`.
261		/// This is the by-reference counterpart of [`Alt::alt`] for `Option`,
262		/// borrowing both arguments and cloning the inner value as needed.
263		#[document_signature]
264		///
265		#[document_type_parameters("The lifetime of the values.", "The type of the value.")]
266		///
267		#[document_parameters("The first option.", "The second option.")]
268		///
269		#[document_returns("The first `Some` value (cloned), or `None`.")]
270		#[document_examples]
271		///
272		/// ```
273		/// use fp_library::{
274		/// 	brands::*,
275		/// 	classes::*,
276		/// 	functions::*,
277		/// };
278		///
279		/// assert_eq!(explicit::alt::<OptionBrand, _, _, _>(&None, &Some(5)), Some(5));
280		/// assert_eq!(explicit::alt::<OptionBrand, _, _, _>(&Some(3), &Some(5)), Some(3));
281		/// assert_eq!(explicit::alt::<OptionBrand, _, _, _>(&None::<i32>, &None), None);
282		/// ```
283		fn ref_alt<'a, A: 'a + Clone>(
284			fa1: &Apply!(<Self as Kind!( type Of<'a, T: 'a>: 'a; )>::Of<'a, A>),
285			fa2: &Apply!(<Self as Kind!( type Of<'a, T: 'a>: 'a; )>::Of<'a, A>),
286		) -> Apply!(<Self as Kind!( type Of<'a, T: 'a>: 'a; )>::Of<'a, A>) {
287			fa1.as_ref().or(fa2.as_ref()).cloned()
288		}
289	}
290
291	impl Plus for OptionBrand {
292		/// Returns `None`, the identity element for [`alt`](Alt::alt).
293		#[document_signature]
294		///
295		#[document_type_parameters("The lifetime of the value.", "The type of the value.")]
296		///
297		#[document_returns("`None`.")]
298		#[document_examples]
299		///
300		/// ```
301		/// use fp_library::{
302		/// 	brands::*,
303		/// 	functions::*,
304		/// };
305		///
306		/// let x: Option<i32> = plus_empty::<OptionBrand, i32>();
307		/// assert_eq!(x, None);
308		/// ```
309		fn empty<'a, A: 'a>() -> Apply!(<Self as Kind!( type Of<'a, T: 'a>: 'a; )>::Of<'a, A>) {
310			None
311		}
312	}
313
314	impl Foldable for OptionBrand {
315		/// Folds the option from the right.
316		///
317		/// 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.
318		#[document_signature]
319		///
320		#[document_type_parameters(
321			"The lifetime of the values.",
322			"The brand of the cloneable function to use.",
323			"The type of the elements in the structure.",
324			"The type of the accumulator."
325		)]
326		///
327		#[document_parameters("The folding function.", "The initial value.", "The option to fold.")]
328		///
329		#[document_returns("`func(a, initial)` if `fa` is `Some(a)`, otherwise `initial`.")]
330		///
331		#[document_examples]
332		///
333		/// ```
334		/// use fp_library::{
335		/// 	brands::*,
336		/// 	functions::*,
337		/// };
338		///
339		/// let x = Some(5);
340		/// let y = explicit::fold_right::<RcFnBrand, OptionBrand, _, _, _, _>(|a, b| a + b, 10, x);
341		/// assert_eq!(y, 15);
342		/// ```
343		fn fold_right<'a, FnBrand, A: 'a + Clone, B: 'a>(
344			func: impl Fn(A, B) -> B + 'a,
345			initial: B,
346			fa: Apply!(<Self as Kind!( type Of<'a, T: 'a>: 'a; )>::Of<'a, A>),
347		) -> B
348		where
349			FnBrand: CloneFn + 'a, {
350			match fa {
351				Some(a) => func(a, initial),
352				None => initial,
353			}
354		}
355
356		/// Folds the option from the left.
357		///
358		/// 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.
359		#[document_signature]
360		///
361		#[document_type_parameters(
362			"The lifetime of the values.",
363			"The brand of the cloneable function to use.",
364			"The type of the elements in the structure.",
365			"The type of the accumulator."
366		)]
367		///
368		#[document_parameters(
369			"The function to apply to the accumulator and each element.",
370			"The initial value of the accumulator.",
371			"The option to fold."
372		)]
373		///
374		#[document_returns("`f(initial, a)` if `fa` is `Some(a)`, otherwise `initial`.")]
375		#[document_examples]
376		///
377		/// ```
378		/// use fp_library::{
379		/// 	brands::*,
380		/// 	functions::*,
381		/// };
382		///
383		/// let x = Some(5);
384		/// let y = explicit::fold_left::<RcFnBrand, OptionBrand, _, _, _, _>(|b, a| b + a, 10, x);
385		/// assert_eq!(y, 15);
386		/// ```
387		fn fold_left<'a, FnBrand, A: 'a + Clone, B: 'a>(
388			func: impl Fn(B, A) -> B + 'a,
389			initial: B,
390			fa: Apply!(<Self as Kind!( type Of<'a, T: 'a>: 'a; )>::Of<'a, A>),
391		) -> B
392		where
393			FnBrand: CloneFn + 'a, {
394			match fa {
395				Some(a) => func(initial, a),
396				None => initial,
397			}
398		}
399
400		/// Maps the value to a monoid and returns it, or returns empty.
401		///
402		/// This method maps the element of the option to a monoid. If the option is `None`, it returns the monoid's identity element.
403		#[document_signature]
404		///
405		#[document_type_parameters(
406			"The lifetime of the values.",
407			"The brand of the cloneable function to use.",
408			"The type of the elements in the structure.",
409			"The type of the monoid."
410		)]
411		///
412		#[document_parameters("The mapping function.", "The option to fold.")]
413		///
414		#[document_returns("`func(a)` if `fa` is `Some(a)`, otherwise `M::empty()`.")]
415		///
416		#[document_examples]
417		///
418		/// ```
419		/// use fp_library::{
420		/// 	brands::*,
421		/// 	functions::*,
422		/// };
423		///
424		/// let x = Some(5);
425		/// let y = explicit::fold_map::<RcFnBrand, OptionBrand, _, _, _, _>(|a: i32| a.to_string(), x);
426		/// assert_eq!(y, "5".to_string());
427		/// ```
428		fn fold_map<'a, FnBrand, A: 'a + Clone, M>(
429			func: impl Fn(A) -> M + 'a,
430			fa: Apply!(<Self as Kind!( type Of<'a, T: 'a>: 'a; )>::Of<'a, A>),
431		) -> M
432		where
433			M: Monoid + 'a,
434			FnBrand: CloneFn + 'a, {
435			match fa {
436				Some(a) => func(a),
437				None => M::empty(),
438			}
439		}
440	}
441
442	impl Traversable for OptionBrand {
443		/// Traverses the option with an applicative function.
444		///
445		/// 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)`.
446		#[document_signature]
447		///
448		#[document_type_parameters(
449			"The lifetime of the values.",
450			"The type of the elements in the traversable structure.",
451			"The type of the elements in the resulting traversable structure.",
452			"The applicative context."
453		)]
454		///
455		#[document_parameters(
456			"The function to apply to each element, returning a value in an applicative context.",
457			"The option to traverse."
458		)]
459		///
460		#[document_returns("The option wrapped in the applicative context.")]
461		#[document_examples]
462		///
463		/// ```
464		/// use fp_library::{
465		/// 	brands::*,
466		/// 	functions::*,
467		/// };
468		///
469		/// let x = Some(5);
470		/// let y =
471		/// 	explicit::traverse::<RcFnBrand, OptionBrand, _, _, OptionBrand, _, _>(|a| Some(a * 2), x);
472		/// assert_eq!(y, Some(Some(10)));
473		/// ```
474		fn traverse<'a, A: 'a + Clone, B: 'a + Clone, F: Applicative>(
475			func: impl Fn(A) -> Apply!(<F as Kind!( type Of<'a, T: 'a>: 'a; )>::Of<'a, B>) + 'a,
476			ta: Apply!(<Self as Kind!( type Of<'a, T: 'a>: 'a; )>::Of<'a, A>),
477		) -> 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>)>)
478		where
479			Apply!(<Self as Kind!( type Of<'a, T: 'a>: 'a; )>::Of<'a, B>): Clone, {
480			match ta {
481				Some(a) => F::map(|b| Some(b), func(a)),
482				None => F::pure(None),
483			}
484		}
485
486		/// Sequences an option of applicative.
487		///
488		/// This method evaluates the computation inside the option and wraps the result in the applicative context. If `None`, it returns `pure(None)`.
489		#[document_signature]
490		///
491		#[document_type_parameters(
492			"The lifetime of the values.",
493			"The type of the elements in the traversable structure.",
494			"The applicative context."
495		)]
496		///
497		#[document_parameters("The option containing the applicative value.")]
498		///
499		#[document_returns("The result of the traversal.")]
500		///
501		/// # Returns
502		///
503		/// The option wrapped in the applicative context.
504		#[document_examples]
505		///
506		/// ```
507		/// use fp_library::{
508		/// 	brands::OptionBrand,
509		/// 	functions::*,
510		/// };
511		///
512		/// let x = Some(Some(5));
513		/// let y = sequence::<OptionBrand, _, OptionBrand>(x);
514		/// assert_eq!(y, Some(Some(5)));
515		/// ```
516		fn sequence<'a, A: 'a + Clone, F: Applicative>(
517			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>)>)
518		) -> 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>)>)
519		where
520			Apply!(<F as Kind!( type Of<'a, T: 'a>: 'a; )>::Of<'a, A>): Clone,
521			Apply!(<Self as Kind!( type Of<'a, T: 'a>: 'a; )>::Of<'a, A>): Clone, {
522			match ta {
523				Some(fa) => F::map(|a| Some(a), fa),
524				None => F::pure(None),
525			}
526		}
527	}
528
529	impl WithIndex for OptionBrand {
530		type Index = ();
531	}
532
533	impl FunctorWithIndex for OptionBrand {
534		/// Maps a function over the value in the option, providing the index `()`.
535		#[document_signature]
536		#[document_type_parameters(
537			"The lifetime of the value.",
538			"The type of the value inside the option.",
539			"The type of the result of applying the function."
540		)]
541		#[document_parameters(
542			"The function to apply to the value and its index.",
543			"The option to map over."
544		)]
545		#[document_returns(
546			"A new option containing the result of applying the function, or `None`."
547		)]
548		#[document_examples]
549		///
550		/// ```
551		/// use fp_library::{
552		/// 	brands::OptionBrand,
553		/// 	classes::functor_with_index::FunctorWithIndex,
554		/// 	functions::*,
555		/// };
556		/// let x = Some(5);
557		/// let y = <OptionBrand as FunctorWithIndex>::map_with_index(|_, i| i * 2, x);
558		/// assert_eq!(y, Some(10));
559		/// ```
560		fn map_with_index<'a, A: 'a, B: 'a>(
561			f: impl Fn((), A) -> B + 'a,
562			fa: Option<A>,
563		) -> Option<B> {
564			fa.map(|a| f((), a))
565		}
566	}
567
568	impl FoldableWithIndex for OptionBrand {
569		/// Folds the option using a monoid, providing the index `()`.
570		#[document_signature]
571		#[document_type_parameters(
572			"The lifetime of the value.",
573			"The brand of the cloneable function to use.",
574			"The type of the value inside the option.",
575			"The monoid type."
576		)]
577		#[document_parameters(
578			"The function to apply to the value and its index.",
579			"The option to fold."
580		)]
581		#[document_returns("The monoid value.")]
582		#[document_examples]
583		///
584		/// ```
585		/// use fp_library::{
586		/// 	brands::*,
587		/// 	classes::foldable_with_index::FoldableWithIndex,
588		/// 	functions::*,
589		/// };
590		/// let x = Some(5);
591		/// let y = <OptionBrand as FoldableWithIndex>::fold_map_with_index::<RcFnBrand, _, _>(
592		/// 	|_, i: i32| i.to_string(),
593		/// 	x,
594		/// );
595		/// assert_eq!(y, "5".to_string());
596		/// ```
597		fn fold_map_with_index<'a, FnBrand, A: 'a + Clone, R: Monoid + 'a>(
598			f: impl Fn((), A) -> R + 'a,
599			fa: Option<A>,
600		) -> R
601		where
602			FnBrand: LiftFn + 'a, {
603			match fa {
604				Some(a) => f((), a),
605				None => R::empty(),
606			}
607		}
608	}
609
610	impl TraversableWithIndex for OptionBrand {
611		/// Traverses the option with an applicative function, providing the index `()`.
612		#[document_signature]
613		#[document_type_parameters(
614			"The lifetime of the value.",
615			"The type of the value inside the option.",
616			"The type of the result.",
617			"The applicative context."
618		)]
619		#[document_parameters(
620			"The function to apply to the value and its index, returning a value in an applicative context.",
621			"The option to traverse."
622		)]
623		#[document_returns("The option wrapped in the applicative context.")]
624		#[document_examples]
625		///
626		/// ```
627		/// use fp_library::{
628		/// 	brands::OptionBrand,
629		/// 	classes::traversable_with_index::TraversableWithIndex,
630		/// 	functions::*,
631		/// };
632		/// let x = Some(5);
633		/// let y = <OptionBrand as TraversableWithIndex>::traverse_with_index::<i32, i32, OptionBrand>(
634		/// 	|_, i| Some(i * 2),
635		/// 	x,
636		/// );
637		/// assert_eq!(y, Some(Some(10)));
638		/// ```
639		fn traverse_with_index<'a, A: 'a, B: 'a + Clone, M: Applicative>(
640			f: impl Fn((), A) -> M::Of<'a, B> + 'a,
641			ta: Option<A>,
642		) -> M::Of<'a, Option<B>> {
643			match ta {
644				Some(a) => M::map(|b| Some(b), f((), a)),
645				None => M::pure(None),
646			}
647		}
648	}
649
650	impl Compactable for OptionBrand {
651		/// Compacts a nested option.
652		///
653		/// This method flattens a nested option.
654		#[document_signature]
655		///
656		#[document_type_parameters("The lifetime of the values.", "The type of the elements.")]
657		///
658		#[document_parameters("The nested option.")]
659		///
660		#[document_returns("The flattened option.")]
661		///
662		#[document_examples]
663		///
664		/// ```
665		/// use fp_library::{
666		/// 	brands::OptionBrand,
667		/// 	functions::*,
668		/// };
669		///
670		/// let x = Some(Some(5));
671		/// let y = explicit::compact::<OptionBrand, _, _, _>(x);
672		/// assert_eq!(y, Some(5));
673		/// ```
674		fn compact<'a, A: 'a>(
675			fa: Apply!(<Self as Kind!( type Of<'a, T: 'a>: 'a; )>::Of<
676			'a,
677			Apply!(<OptionBrand as Kind!( type Of<'a, T: 'a>: 'a; )>::Of<'a, A>),
678		>)
679		) -> Apply!(<Self as Kind!( type Of<'a, T: 'a>: 'a; )>::Of<'a, A>) {
680			fa.flatten()
681		}
682
683		/// Separates an option of result.
684		///
685		/// This method separates an option of result into a pair of options.
686		#[document_signature]
687		///
688		#[document_type_parameters(
689			"The lifetime of the values.",
690			"The type of the error value.",
691			"The type of the success value."
692		)]
693		///
694		#[document_parameters("The option of result.")]
695		///
696		#[document_returns("A pair of options.")]
697		///
698		#[document_examples]
699		///
700		/// ```
701		/// use fp_library::{
702		/// 	brands::*,
703		/// 	functions::*,
704		/// };
705		///
706		/// let x: Option<Result<i32, &str>> = Some(Ok(5));
707		/// let (errs, oks) = explicit::separate::<OptionBrand, _, _, _, _>(x);
708		/// assert_eq!(oks, Some(5));
709		/// assert_eq!(errs, None);
710		/// ```
711		fn separate<'a, E: 'a, O: 'a>(
712			fa: Apply!(<Self as Kind!( type Of<'a, T: 'a>: 'a; )>::Of<'a, Result<O, E>>)
713		) -> (
714			Apply!(<Self as Kind!( type Of<'a, T: 'a>: 'a; )>::Of<'a, E>),
715			Apply!(<Self as Kind!( type Of<'a, T: 'a>: 'a; )>::Of<'a, O>),
716		) {
717			match fa {
718				Some(Ok(o)) => (None, Some(o)),
719				Some(Err(e)) => (Some(e), None),
720				None => (None, None),
721			}
722		}
723	}
724
725	impl RefCompactable for OptionBrand {
726		/// Compacts a borrowed nested option by reference.
727		///
728		/// Flattens a borrowed `Option<Option<A>>` into an `Option<A>`,
729		/// cloning the inner value if present.
730		#[document_signature]
731		///
732		#[document_type_parameters(
733			"The lifetime of the values.",
734			"The type of the elements. Must be [`Clone`] because elements are extracted from a borrowed container."
735		)]
736		///
737		#[document_parameters("A reference to the nested option.")]
738		///
739		#[document_returns("The flattened option with the inner value cloned, or [`None`].")]
740		///
741		#[document_examples]
742		///
743		/// ```
744		/// use fp_library::{
745		/// 	brands::OptionBrand,
746		/// 	functions::*,
747		/// };
748		///
749		/// let x = Some(Some(5));
750		/// let y = explicit::compact::<OptionBrand, _, _, _>(&x);
751		/// assert_eq!(y, Some(5));
752		///
753		/// let z: Option<Option<i32>> = Some(None);
754		/// let w = explicit::compact::<OptionBrand, _, _, _>(&z);
755		/// assert_eq!(w, None);
756		/// ```
757		fn ref_compact<'a, A: 'a + Clone>(
758			fa: &Apply!(<Self as Kind!( type Of<'a, T: 'a>: 'a; )>::Of<'a, Option<A>>)
759		) -> Apply!(<Self as Kind!( type Of<'a, T: 'a>: 'a; )>::Of<'a, A>) {
760			match fa {
761				Some(Some(a)) => Some(a.clone()),
762				_ => None,
763			}
764		}
765
766		/// Separates a borrowed option of result by reference.
767		///
768		/// Splits a borrowed `Option<Result<O, E>>` into a pair of options,
769		/// cloning the inner value. The first element contains the error if
770		/// present, the second contains the success value.
771		#[document_signature]
772		///
773		#[document_type_parameters(
774			"The lifetime of the values.",
775			"The type of the error value. Must be [`Clone`] because elements are extracted from a borrowed container.",
776			"The type of the success value. Must be [`Clone`] because elements are extracted from a borrowed container."
777		)]
778		///
779		#[document_parameters("A reference to the option of result.")]
780		///
781		#[document_returns(
782			"A pair of options: the first containing the cloned error, the second containing the cloned success value."
783		)]
784		///
785		#[document_examples]
786		///
787		/// ```
788		/// use fp_library::{
789		/// 	brands::*,
790		/// 	functions::*,
791		/// };
792		///
793		/// let x: Option<Result<i32, &str>> = Some(Ok(5));
794		/// let (errs, oks) = explicit::separate::<OptionBrand, _, _, _, _>(&x);
795		/// assert_eq!(oks, Some(5));
796		/// assert_eq!(errs, None);
797		///
798		/// let y: Option<Result<i32, &str>> = Some(Err("bad"));
799		/// let (errs, oks) = explicit::separate::<OptionBrand, _, _, _, _>(&y);
800		/// assert_eq!(oks, None);
801		/// assert_eq!(errs, Some("bad"));
802		/// ```
803		fn ref_separate<'a, E: 'a + Clone, O: 'a + Clone>(
804			fa: &Apply!(<Self as Kind!( type Of<'a, T: 'a>: 'a; )>::Of<'a, Result<O, E>>)
805		) -> (
806			Apply!(<Self as Kind!( type Of<'a, T: 'a>: 'a; )>::Of<'a, E>),
807			Apply!(<Self as Kind!( type Of<'a, T: 'a>: 'a; )>::Of<'a, O>),
808		) {
809			match fa {
810				Some(Ok(o)) => (None, Some(o.clone())),
811				Some(Err(e)) => (Some(e.clone()), None),
812				None => (None, None),
813			}
814		}
815	}
816
817	impl Filterable for OptionBrand {
818		/// Partitions an option based on a function that returns a result.
819		///
820		/// This method partitions an option based on a function that returns a result.
821		#[document_signature]
822		///
823		#[document_type_parameters(
824			"The lifetime of the values.",
825			"The type of the input value.",
826			"The type of the error value.",
827			"The type of the success value."
828		)]
829		///
830		#[document_parameters("The function to apply.", "The option to partition.")]
831		///
832		#[document_returns("A pair of options.")]
833		///
834		#[document_examples]
835		///
836		/// ```
837		/// use fp_library::{
838		/// 	brands::*,
839		/// 	functions::*,
840		/// };
841		///
842		/// let x = Some(5);
843		/// let (errs, oks) = explicit::partition_map::<OptionBrand, _, _, _, _, _>(
844		/// 	|a| if a > 2 { Ok(a) } else { Err(a) },
845		/// 	x,
846		/// );
847		/// assert_eq!(oks, Some(5));
848		/// assert_eq!(errs, None);
849		/// ```
850		fn partition_map<'a, A: 'a, E: 'a, O: 'a>(
851			func: impl Fn(A) -> Result<O, E> + 'a,
852			fa: Apply!(<Self as Kind!( type Of<'a, T: 'a>: 'a; )>::Of<'a, A>),
853		) -> (
854			Apply!(<Self as Kind!( type Of<'a, T: 'a>: 'a; )>::Of<'a, E>),
855			Apply!(<Self as Kind!( type Of<'a, T: 'a>: 'a; )>::Of<'a, O>),
856		) {
857			match fa {
858				Some(a) => match func(a) {
859					Ok(o) => (None, Some(o)),
860					Err(e) => (Some(e), None),
861				},
862				None => (None, None),
863			}
864		}
865
866		/// Partitions an option based on a predicate.
867		///
868		/// This method partitions an option based on a predicate.
869		#[document_signature]
870		///
871		#[document_type_parameters("The lifetime of the values.", "The type of the elements.")]
872		///
873		#[document_parameters("The predicate.", "The option to partition.")]
874		///
875		#[document_returns("A pair of options.")]
876		///
877		#[document_examples]
878		///
879		/// ```
880		/// use fp_library::{
881		/// 	brands::*,
882		/// 	functions::*,
883		/// };
884		///
885		/// let x = Some(5);
886		/// let (not_satisfied, satisfied) = explicit::partition::<OptionBrand, _, _, _>(|a| a > 2, x);
887		/// assert_eq!(satisfied, Some(5));
888		/// assert_eq!(not_satisfied, None);
889		/// ```
890		fn partition<'a, A: 'a + Clone>(
891			func: impl Fn(A) -> bool + 'a,
892			fa: Apply!(<Self as Kind!( type Of<'a, T: 'a>: 'a; )>::Of<'a, A>),
893		) -> (
894			Apply!(<Self as Kind!( type Of<'a, T: 'a>: 'a; )>::Of<'a, A>),
895			Apply!(<Self as Kind!( type Of<'a, T: 'a>: 'a; )>::Of<'a, A>),
896		) {
897			match fa {
898				Some(a) =>
899					if func(a.clone()) {
900						(None, Some(a))
901					} else {
902						(Some(a), None)
903					},
904				None => (None, None),
905			}
906		}
907
908		/// Maps a function over an option and filters out `None` results.
909		///
910		/// This method maps a function over an option and filters out `None` results.
911		#[document_signature]
912		///
913		#[document_type_parameters(
914			"The lifetime of the values.",
915			"The type of the input value.",
916			"The type of the result of applying the function."
917		)]
918		///
919		#[document_parameters("The function to apply.", "The option to filter and map.")]
920		///
921		#[document_returns("The filtered and mapped option.")]
922		///
923		#[document_examples]
924		///
925		/// ```
926		/// use fp_library::{
927		/// 	brands::OptionBrand,
928		/// 	functions::*,
929		/// };
930		///
931		/// let x = Some(5);
932		/// let y = explicit::filter_map::<OptionBrand, _, _, _, _>(
933		/// 	|a| if a > 2 { Some(a * 2) } else { None },
934		/// 	x,
935		/// );
936		/// assert_eq!(y, Some(10));
937		/// ```
938		fn filter_map<'a, A: 'a, B: 'a>(
939			func: impl Fn(A) -> Option<B> + 'a,
940			fa: Apply!(<Self as Kind!( type Of<'a, T: 'a>: 'a; )>::Of<'a, A>),
941		) -> Apply!(<Self as Kind!( type Of<'a, T: 'a>: 'a; )>::Of<'a, B>) {
942			fa.and_then(func)
943		}
944
945		/// Filters an option based on a predicate.
946		///
947		/// This method filters an option based on a predicate.
948		#[document_signature]
949		///
950		#[document_type_parameters("The lifetime of the values.", "The type of the elements.")]
951		///
952		#[document_parameters("The predicate.", "The option to filter.")]
953		///
954		#[document_returns("The filtered option.")]
955		///
956		#[document_examples]
957		///
958		/// ```
959		/// use fp_library::{
960		/// 	brands::OptionBrand,
961		/// 	functions::*,
962		/// };
963		///
964		/// let x = Some(5);
965		/// let y = explicit::filter::<OptionBrand, _, _, _>(|a| a > 2, x);
966		/// assert_eq!(y, Some(5));
967		/// ```
968		fn filter<'a, A: 'a + Clone>(
969			func: impl Fn(A) -> bool + 'a,
970			fa: Apply!(<Self as Kind!( type Of<'a, T: 'a>: 'a; )>::Of<'a, A>),
971		) -> Apply!(<Self as Kind!( type Of<'a, T: 'a>: 'a; )>::Of<'a, A>) {
972			fa.filter(|a| func(a.clone()))
973		}
974	}
975
976	impl Witherable for OptionBrand {
977		/// Partitions an option based on a function that returns a result in an applicative context.
978		///
979		/// This method partitions an option based on a function that returns a result in an applicative context.
980		#[document_signature]
981		///
982		#[document_type_parameters(
983			"The lifetime of the values.",
984			"The applicative context.",
985			"The type of the elements in the input structure.",
986			"The type of the error values.",
987			"The type of the success values."
988		)]
989		///
990		#[document_parameters(
991			"The function to apply to each element, returning a `Result` in an applicative context.",
992			"The option to partition."
993		)]
994		///
995		#[document_returns("The partitioned option wrapped in the applicative context.")]
996		#[document_examples]
997		///
998		/// ```
999		/// use fp_library::{
1000		/// 	brands::*,
1001		/// 	functions::*,
1002		/// };
1003		///
1004		/// let x = Some(5);
1005		/// let y = explicit::wilt::<RcFnBrand, OptionBrand, OptionBrand, _, _, _, _, _>(
1006		/// 	|a| Some(if a > 2 { Ok(a) } else { Err(a) }),
1007		/// 	x,
1008		/// );
1009		/// assert_eq!(y, Some((None, Some(5))));
1010		/// ```
1011		fn wilt<'a, M: Applicative, A: 'a + Clone, E: 'a + Clone, O: 'a + Clone>(
1012			func: impl Fn(A) -> Apply!(<M as Kind!( type Of<'a, T: 'a>: 'a; )>::Of<'a, Result<O, E>>)
1013			+ 'a,
1014			ta: Apply!(<Self as Kind!( type Of<'a, T: 'a>: 'a; )>::Of<'a, A>),
1015		) -> Apply!(<M as Kind!( type Of<'a, T: 'a>: 'a; )>::Of<
1016		'a,
1017		(
1018			Apply!(<Self as Kind!( type Of<'a, T: 'a>: 'a; )>::Of<'a, E>),
1019			Apply!(<Self as Kind!( type Of<'a, T: 'a>: 'a; )>::Of<'a, O>),
1020		),
1021	>)
1022		where
1023			Apply!(<Self as Kind!( type Of<'a, T: 'a>: 'a; )>::Of<'a, Result<O, E>>): Clone,
1024			Apply!(<M as Kind!( type Of<'a, T: 'a>: 'a; )>::Of<'a, Result<O, E>>): Clone, {
1025			match ta {
1026				Some(a) => M::map(
1027					|res| match res {
1028						Ok(o) => (None, Some(o)),
1029						Err(e) => (Some(e), None),
1030					},
1031					func(a),
1032				),
1033				None => M::pure((None, None)),
1034			}
1035		}
1036
1037		/// Maps a function over an option and filters out `None` results in an applicative context.
1038		///
1039		/// This method maps a function over an option and filters out `None` results in an applicative context.
1040		#[document_signature]
1041		///
1042		#[document_type_parameters(
1043			"The lifetime of the values.",
1044			"The applicative context.",
1045			"The type of the elements in the input structure.",
1046			"The type of the result of applying the function."
1047		)]
1048		///
1049		#[document_parameters(
1050			"The function to apply to each element, returning an `Option` in an applicative context.",
1051			"The option to filter and map."
1052		)]
1053		///
1054		#[document_returns("The filtered and mapped option wrapped in the applicative context.")]
1055		#[document_examples]
1056		///
1057		/// ```
1058		/// use fp_library::{
1059		/// 	brands::*,
1060		/// 	functions::*,
1061		/// };
1062		///
1063		/// let x = Some(5);
1064		/// let y = explicit::wither::<RcFnBrand, OptionBrand, OptionBrand, _, _, _, _>(
1065		/// 	|a| Some(if a > 2 { Some(a * 2) } else { None }),
1066		/// 	x,
1067		/// );
1068		/// assert_eq!(y, Some(Some(10)));
1069		/// ```
1070		fn wither<'a, M: Applicative, A: 'a + Clone, B: 'a + Clone>(
1071			func: impl Fn(A) -> Apply!(<M as Kind!( type Of<'a, T: 'a>: 'a; )>::Of<'a, Option<B>>) + 'a,
1072			ta: Apply!(<Self as Kind!( type Of<'a, T: 'a>: 'a; )>::Of<'a, A>),
1073		) -> Apply!(<M as Kind!( type Of<'a, T: 'a>: 'a; )>::Of<
1074		'a,
1075		Apply!(<Self as Kind!( type Of<'a, T: 'a>: 'a; )>::Of<'a, B>),
1076	>)
1077		where
1078			Apply!(<Self as Kind!( type Of<'a, T: 'a>: 'a; )>::Of<'a, Option<B>>): Clone,
1079			Apply!(<M as Kind!( type Of<'a, T: 'a>: 'a; )>::Of<'a, Option<B>>): Clone, {
1080			match ta {
1081				Some(a) => func(a),
1082				None => M::pure(None),
1083			}
1084		}
1085	}
1086
1087	impl MonadRec for OptionBrand {
1088		/// Performs tail-recursive monadic computation over [`Option`].
1089		///
1090		/// Iteratively applies the step function. If the function returns [`None`],
1091		/// the computation short-circuits. If it returns `Some(ControlFlow::Continue(a))`, the
1092		/// loop continues with the new state. If it returns `Some(ControlFlow::Break(b))`,
1093		/// the computation completes with `Some(b)`.
1094		#[document_signature]
1095		///
1096		#[document_type_parameters(
1097			"The lifetime of the computation.",
1098			"The type of the initial value and loop state.",
1099			"The type of the result."
1100		)]
1101		///
1102		#[document_parameters("The step function.", "The initial value.")]
1103		///
1104		#[document_returns(
1105			"The result of the computation, or `None` if the step function returned `None`."
1106		)]
1107		///
1108		#[document_examples]
1109		///
1110		/// ```
1111		/// use {
1112		/// 	core::ops::ControlFlow,
1113		/// 	fp_library::{
1114		/// 		brands::*,
1115		/// 		functions::*,
1116		/// 		types::*,
1117		/// 	},
1118		/// };
1119		///
1120		/// let result = tail_rec_m::<OptionBrand, _, _>(
1121		/// 	|n| {
1122		/// 		if n < 10 { Some(ControlFlow::Continue(n + 1)) } else { Some(ControlFlow::Break(n)) }
1123		/// 	},
1124		/// 	0,
1125		/// );
1126		/// assert_eq!(result, Some(10));
1127		/// ```
1128		fn tail_rec_m<'a, A: 'a, B: 'a>(
1129			func: impl Fn(
1130				A,
1131			)
1132				-> Apply!(<Self as Kind!( type Of<'a, T: 'a>: 'a; )>::Of<'a, ControlFlow<B, A>>)
1133			+ 'a,
1134			initial: A,
1135		) -> Apply!(<Self as Kind!( type Of<'a, T: 'a>: 'a; )>::Of<'a, B>) {
1136			let mut current = initial;
1137			loop {
1138				match func(current) {
1139					None => return None,
1140					Some(ControlFlow::Continue(next)) => current = next,
1141					Some(ControlFlow::Break(b)) => return Some(b),
1142				}
1143			}
1144		}
1145	}
1146
1147	// -- By-reference trait implementations --
1148
1149	impl RefFunctor for OptionBrand {
1150		/// Maps a function over the option by reference.
1151		#[document_signature]
1152		#[document_type_parameters("The lifetime.", "The input type.", "The output type.")]
1153		#[document_parameters("The function.", "The option.")]
1154		#[document_returns("The mapped option.")]
1155		#[document_examples]
1156		///
1157		/// ```
1158		/// use fp_library::{
1159		/// 	brands::*,
1160		/// 	functions::*,
1161		/// };
1162		/// assert_eq!(explicit::map::<OptionBrand, _, _, _, _>(|x: &i32| *x * 2, &Some(5)), Some(10));
1163		/// ```
1164		fn ref_map<'a, A: 'a, B: 'a>(
1165			func: impl Fn(&A) -> B + 'a,
1166			fa: &Apply!(<Self as Kind!( type Of<'a, T: 'a>: 'a; )>::Of<'a, A>),
1167		) -> Apply!(<Self as Kind!( type Of<'a, T: 'a>: 'a; )>::Of<'a, B>) {
1168			fa.as_ref().map(func)
1169		}
1170	}
1171
1172	impl RefFoldable for OptionBrand {
1173		/// Folds the option by reference.
1174		#[document_signature]
1175		#[document_type_parameters(
1176			"The lifetime.",
1177			"The brand.",
1178			"The element type.",
1179			"The monoid type."
1180		)]
1181		#[document_parameters("The mapping function.", "The option.")]
1182		#[document_returns("The monoid value.")]
1183		#[document_examples]
1184		///
1185		/// ```
1186		/// use fp_library::{
1187		/// 	brands::*,
1188		/// 	functions::*,
1189		/// };
1190		/// let result =
1191		/// 	explicit::fold_map::<RcFnBrand, OptionBrand, _, _, _, _>(|x: &i32| x.to_string(), &Some(5));
1192		/// assert_eq!(result, "5");
1193		/// ```
1194		fn ref_fold_map<'a, FnBrand, A: 'a + Clone, M>(
1195			func: impl Fn(&A) -> M + 'a,
1196			fa: &Apply!(<Self as Kind!( type Of<'a, T: 'a>: 'a; )>::Of<'a, A>),
1197		) -> M
1198		where
1199			FnBrand: LiftFn + 'a,
1200			M: Monoid + 'a, {
1201			match fa {
1202				Some(a) => func(a),
1203				None => Monoid::empty(),
1204			}
1205		}
1206	}
1207
1208	impl RefFilterable for OptionBrand {
1209		/// Filters and maps the option by reference.
1210		#[document_signature]
1211		#[document_type_parameters("The lifetime.", "The input type.", "The output type.")]
1212		#[document_parameters("The function.", "The option.")]
1213		#[document_returns("The filtered option.")]
1214		#[document_examples]
1215		///
1216		/// ```
1217		/// use fp_library::{
1218		/// 	brands::*,
1219		/// 	functions::*,
1220		/// };
1221		/// let result = explicit::filter_map::<OptionBrand, _, _, _, _>(
1222		/// 	|x: &i32| if *x > 3 { Some(*x) } else { None },
1223		/// 	&Some(5),
1224		/// );
1225		/// assert_eq!(result, Some(5));
1226		/// ```
1227		fn ref_filter_map<'a, A: 'a, B: 'a>(
1228			func: impl Fn(&A) -> Option<B> + 'a,
1229			fa: &Apply!(<Self as Kind!( type Of<'a, T: 'a>: 'a; )>::Of<'a, A>),
1230		) -> Apply!(<Self as Kind!( type Of<'a, T: 'a>: 'a; )>::Of<'a, B>) {
1231			fa.as_ref().and_then(func)
1232		}
1233	}
1234
1235	impl RefTraversable for OptionBrand {
1236		/// Traverses the option by reference.
1237		#[document_signature]
1238		#[document_type_parameters(
1239			"The lifetime.",
1240			"The brand.",
1241			"The input type.",
1242			"The output type.",
1243			"The applicative."
1244		)]
1245		#[document_parameters("The function.", "The option.")]
1246		#[document_returns("The traversed result.")]
1247		#[document_examples]
1248		///
1249		/// ```
1250		/// use fp_library::{
1251		/// 	brands::*,
1252		/// 	functions::*,
1253		/// };
1254		/// let result: Vec<Option<String>> = ref_traverse::<OptionBrand, RcFnBrand, _, _, VecBrand>(
1255		/// 	|x: &i32| vec![x.to_string()],
1256		/// 	&Some(5),
1257		/// );
1258		/// assert_eq!(result, vec![Some("5".to_string())]);
1259		/// ```
1260		fn ref_traverse<'a, FnBrand, A: 'a + Clone, B: 'a + Clone, F: Applicative>(
1261			func: impl Fn(&A) -> Apply!(<F as Kind!( type Of<'a, T: 'a>: 'a; )>::Of<'a, B>) + 'a,
1262			ta: &Apply!(<Self as Kind!( type Of<'a, T: 'a>: 'a; )>::Of<'a, A>),
1263		) -> 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>)>)
1264		where
1265			FnBrand: LiftFn + 'a,
1266			Apply!(<Self as Kind!( type Of<'a, T: 'a>: 'a; )>::Of<'a, B>): Clone,
1267			Apply!(<F as Kind!( type Of<'a, T: 'a>: 'a; )>::Of<'a, B>): Clone, {
1268			match ta {
1269				Some(a) => F::map(|b| Some(b), func(a)),
1270				None => F::pure(None),
1271			}
1272		}
1273	}
1274
1275	impl RefWitherable for OptionBrand {}
1276
1277	impl RefFunctorWithIndex for OptionBrand {
1278		/// Maps by reference with index (always `()`).
1279		#[document_signature]
1280		#[document_type_parameters("The lifetime.", "The input type.", "The output type.")]
1281		#[document_parameters("The function.", "The option.")]
1282		#[document_returns("The mapped option.")]
1283		#[document_examples]
1284		///
1285		/// ```
1286		/// use fp_library::{
1287		/// 	brands::*,
1288		/// 	functions::*,
1289		/// };
1290		/// assert_eq!(
1291		/// 	explicit::map_with_index::<OptionBrand, _, _, _, _>(|(), x: &i32| *x * 2, &Some(5)),
1292		/// 	Some(10),
1293		/// );
1294		/// ```
1295		fn ref_map_with_index<'a, A: 'a, B: 'a>(
1296			func: impl Fn((), &A) -> B + 'a,
1297			fa: &Apply!(<Self as Kind!( type Of<'a, T: 'a>: 'a; )>::Of<'a, A>),
1298		) -> Apply!(<Self as Kind!( type Of<'a, T: 'a>: 'a; )>::Of<'a, B>) {
1299			fa.as_ref().map(|a| func((), a))
1300		}
1301	}
1302
1303	impl RefFoldableWithIndex for OptionBrand {
1304		/// Folds by reference with index (always `()`).
1305		#[document_signature]
1306		#[document_type_parameters(
1307			"The lifetime.",
1308			"The brand of the cloneable function.",
1309			"The element type.",
1310			"The monoid type."
1311		)]
1312		#[document_parameters("The function.", "The option.")]
1313		#[document_returns("The monoid value.")]
1314		#[document_examples]
1315		///
1316		/// ```
1317		/// use fp_library::{
1318		/// 	brands::*,
1319		/// 	functions::*,
1320		/// };
1321		/// let result = explicit::fold_map_with_index::<RcFnBrand, OptionBrand, _, _, _, _>(
1322		/// 	|(), x: &i32| x.to_string(),
1323		/// 	&Some(5),
1324		/// );
1325		/// assert_eq!(result, "5");
1326		/// ```
1327		fn ref_fold_map_with_index<'a, FnBrand, A: 'a + Clone, R: Monoid + 'a>(
1328			func: impl Fn((), &A) -> R + 'a,
1329			fa: &Apply!(<Self as Kind!( type Of<'a, T: 'a>: 'a; )>::Of<'a, A>),
1330		) -> R
1331		where
1332			FnBrand: LiftFn + 'a, {
1333			match fa {
1334				Some(a) => func((), a),
1335				None => Monoid::empty(),
1336			}
1337		}
1338	}
1339
1340	impl RefTraversableWithIndex for OptionBrand {
1341		/// Traverses by reference with index (always `()`).
1342		#[document_signature]
1343		#[document_type_parameters(
1344			"The lifetime.",
1345			"The input type.",
1346			"The output type.",
1347			"The applicative."
1348		)]
1349		#[document_parameters("The function.", "The option.")]
1350		#[document_returns("The traversed result.")]
1351		#[document_examples]
1352		///
1353		/// ```
1354		/// use fp_library::{
1355		/// 	brands::*,
1356		/// 	functions::*,
1357		/// };
1358		/// let result: Vec<Option<String>> =
1359		/// 	explicit::traverse_with_index::<RcFnBrand, OptionBrand, _, _, VecBrand, _, _>(
1360		/// 		|(), x: &i32| vec![x.to_string()],
1361		/// 		&Some(5),
1362		/// 	);
1363		/// assert_eq!(result, vec![Some("5".to_string())]);
1364		/// ```
1365		fn ref_traverse_with_index<'a, A: 'a + Clone, B: 'a + Clone, M: Applicative>(
1366			f: impl Fn((), &A) -> Apply!(<M as Kind!( type Of<'a, T: 'a>: 'a; )>::Of<'a, B>) + 'a,
1367			ta: &Apply!(<Self as Kind!( type Of<'a, T: 'a>: 'a; )>::Of<'a, A>),
1368		) -> Apply!(<M as Kind!( type Of<'a, T: 'a>: 'a; )>::Of<'a, Apply!(<Self as Kind!( type Of<'a, T: 'a>: 'a; )>::Of<'a, B>)>)
1369		where
1370			Apply!(<Self as Kind!( type Of<'a, T: 'a>: 'a; )>::Of<'a, B>): Clone,
1371			Apply!(<M as Kind!( type Of<'a, T: 'a>: 'a; )>::Of<'a, B>): Clone, {
1372			match ta {
1373				Some(a) => M::map(|b| Some(b), f((), a)),
1374				None => M::pure(None),
1375			}
1376		}
1377	}
1378
1379	// -- By-reference monadic trait implementations --
1380
1381	impl RefPointed for OptionBrand {
1382		/// Creates a `Some` from a reference by cloning.
1383		#[document_signature]
1384		#[document_type_parameters("The lifetime of the value.", "The type of the value.")]
1385		#[document_parameters("The reference to the value to wrap.")]
1386		#[document_returns("A `Some` containing a clone of the value.")]
1387		#[document_examples]
1388		///
1389		/// ```
1390		/// use fp_library::{
1391		/// 	brands::*,
1392		/// 	functions::*,
1393		/// };
1394		///
1395		/// let x = 42;
1396		/// let result: Option<i32> = ref_pure::<OptionBrand, _>(&x);
1397		/// assert_eq!(result, Some(42));
1398		/// ```
1399		fn ref_pure<'a, A: Clone + 'a>(
1400			a: &A
1401		) -> Apply!(<Self as Kind!( type Of<'a, T: 'a>: 'a; )>::Of<'a, A>) {
1402			Some(a.clone())
1403		}
1404	}
1405
1406	impl RefLift for OptionBrand {
1407		/// Combines two `Option` values with a by-reference binary function.
1408		#[document_signature]
1409		#[document_type_parameters(
1410			"The lifetime.",
1411			"First input type.",
1412			"Second input type.",
1413			"Output type."
1414		)]
1415		#[document_parameters("The binary function.", "The first option.", "The second option.")]
1416		#[document_returns("The combined result, or `None` if either input is `None`.")]
1417		#[document_examples]
1418		///
1419		/// ```
1420		/// use fp_library::{
1421		/// 	brands::*,
1422		/// 	functions::*,
1423		/// };
1424		///
1425		/// let result = explicit::lift2::<OptionBrand, _, _, _, _, _, _>(
1426		/// 	|a: &i32, b: &i32| *a + *b,
1427		/// 	&Some(1),
1428		/// 	&Some(2),
1429		/// );
1430		/// assert_eq!(result, Some(3));
1431		/// ```
1432		fn ref_lift2<'a, A: 'a, B: 'a, C: 'a>(
1433			func: impl Fn(&A, &B) -> C + 'a,
1434			fa: &Apply!(<Self as Kind!( type Of<'a, T: 'a>: 'a; )>::Of<'a, A>),
1435			fb: &Apply!(<Self as Kind!( type Of<'a, T: 'a>: 'a; )>::Of<'a, B>),
1436		) -> Apply!(<Self as Kind!( type Of<'a, T: 'a>: 'a; )>::Of<'a, C>) {
1437			match (fa.as_ref(), fb.as_ref()) {
1438				(Some(a), Some(b)) => Some(func(a, b)),
1439				_ => None,
1440			}
1441		}
1442	}
1443
1444	impl RefSemiapplicative for OptionBrand {
1445		/// Applies a wrapped by-ref function to an `Option` value.
1446		#[document_signature]
1447		#[document_type_parameters(
1448			"The lifetime.",
1449			"The function brand.",
1450			"The input type.",
1451			"The output type."
1452		)]
1453		#[document_parameters(
1454			"The option containing the by-ref function.",
1455			"The option containing the value."
1456		)]
1457		#[document_returns("The result of applying the function, or `None`.")]
1458		#[document_examples]
1459		///
1460		/// ```
1461		/// use fp_library::{
1462		/// 	brands::*,
1463		/// 	classes::*,
1464		/// 	functions::*,
1465		/// };
1466		///
1467		/// let f: std::rc::Rc<dyn Fn(&i32) -> i32> = std::rc::Rc::new(|x: &i32| *x + 1);
1468		/// let result = ref_apply::<RcFnBrand, OptionBrand, _, _>(&Some(f), &Some(5));
1469		/// assert_eq!(result, Some(6));
1470		/// ```
1471		fn ref_apply<'a, FnBrand: 'a + CloneFn<Ref>, A: 'a, B: 'a>(
1472			ff: &Apply!(<Self as Kind!( type Of<'a, T: 'a>: 'a; )>::Of<'a, <FnBrand as CloneFn<Ref>>::Of<'a, A, B>>),
1473			fa: &Apply!(<Self as Kind!( type Of<'a, T: 'a>: 'a; )>::Of<'a, A>),
1474		) -> Apply!(<Self as Kind!( type Of<'a, T: 'a>: 'a; )>::Of<'a, B>) {
1475			match (ff, fa.as_ref()) {
1476				(Some(f), Some(a)) => Some((**f)(a)),
1477				_ => None,
1478			}
1479		}
1480	}
1481
1482	impl RefSemimonad for OptionBrand {
1483		/// Chains `Option` computations by reference.
1484		#[document_signature]
1485		#[document_type_parameters("The lifetime.", "The input type.", "The output type.")]
1486		#[document_parameters("The input option.", "The function to apply by reference.")]
1487		#[document_returns("The result of applying the function, or `None`.")]
1488		#[document_examples]
1489		///
1490		/// ```
1491		/// use fp_library::{
1492		/// 	brands::*,
1493		/// 	functions::*,
1494		/// };
1495		///
1496		/// let result: Option<String> =
1497		/// 	explicit::bind::<OptionBrand, _, _, _, _>(&Some(42), |x: &i32| Some(x.to_string()));
1498		/// assert_eq!(result, Some("42".to_string()));
1499		/// ```
1500		fn ref_bind<'a, A: 'a, B: 'a>(
1501			fa: &Apply!(<Self as Kind!( type Of<'a, T: 'a>: 'a; )>::Of<'a, A>),
1502			f: impl Fn(&A) -> Apply!(<Self as Kind!( type Of<'a, T: 'a>: 'a; )>::Of<'a, B>) + 'a,
1503		) -> Apply!(<Self as Kind!( type Of<'a, T: 'a>: 'a; )>::Of<'a, B>) {
1504			fa.as_ref().and_then(f)
1505		}
1506	}
1507}
1508
1509#[cfg(test)]
1510mod tests {
1511
1512	use {
1513		crate::{
1514			brands::*,
1515			classes::*,
1516			functions::*,
1517		},
1518		quickcheck_macros::quickcheck,
1519	};
1520
1521	// Functor Laws
1522
1523	/// Tests the identity law for Functor.
1524	#[quickcheck]
1525	fn functor_identity(x: Option<i32>) -> bool {
1526		explicit::map::<OptionBrand, _, _, _, _>(identity, x) == x
1527	}
1528
1529	/// Tests the composition law for Functor.
1530	#[quickcheck]
1531	fn functor_composition(x: Option<i32>) -> bool {
1532		let f = |x: i32| x.wrapping_add(1);
1533		let g = |x: i32| x.wrapping_mul(2);
1534		explicit::map::<OptionBrand, _, _, _, _>(compose(f, g), x)
1535			== explicit::map::<OptionBrand, _, _, _, _>(
1536				f,
1537				explicit::map::<OptionBrand, _, _, _, _>(g, x),
1538			)
1539	}
1540
1541	// Applicative Laws
1542
1543	/// Tests the identity law for Applicative.
1544	#[quickcheck]
1545	fn applicative_identity(v: Option<i32>) -> bool {
1546		apply::<RcFnBrand, OptionBrand, _, _>(
1547			pure::<OptionBrand, _>(<RcFnBrand as LiftFn>::new(identity)),
1548			v,
1549		) == v
1550	}
1551
1552	/// Tests the homomorphism law for Applicative.
1553	#[quickcheck]
1554	fn applicative_homomorphism(x: i32) -> bool {
1555		let f = |x: i32| x.wrapping_mul(2);
1556		apply::<RcFnBrand, OptionBrand, _, _>(
1557			pure::<OptionBrand, _>(<RcFnBrand as LiftFn>::new(f)),
1558			pure::<OptionBrand, _>(x),
1559		) == pure::<OptionBrand, _>(f(x))
1560	}
1561
1562	/// Tests the composition law for Applicative.
1563	#[quickcheck]
1564	fn applicative_composition(
1565		w: Option<i32>,
1566		u_is_some: bool,
1567		v_is_some: bool,
1568	) -> bool {
1569		let v_fn = |x: i32| x.wrapping_mul(2);
1570		let u_fn = |x: i32| x.wrapping_add(1);
1571
1572		let v =
1573			if v_is_some { pure::<OptionBrand, _>(<RcFnBrand as LiftFn>::new(v_fn)) } else { None };
1574		let u =
1575			if u_is_some { pure::<OptionBrand, _>(<RcFnBrand as LiftFn>::new(u_fn)) } else { None };
1576
1577		// RHS: u <*> (v <*> w)
1578		let vw = apply::<RcFnBrand, OptionBrand, _, _>(v.clone(), w);
1579		let rhs = apply::<RcFnBrand, OptionBrand, _, _>(u.clone(), vw);
1580
1581		// LHS: pure(compose) <*> u <*> v <*> w
1582		// equivalent to (u . v) <*> w
1583		let uv = match (u, v) {
1584			(Some(uf), Some(vf)) => {
1585				let composed = move |x| uf(vf(x));
1586				Some(<RcFnBrand as LiftFn>::new(composed))
1587			}
1588			_ => None,
1589		};
1590
1591		let lhs = apply::<RcFnBrand, OptionBrand, _, _>(uv, w);
1592
1593		lhs == rhs
1594	}
1595
1596	/// Tests the interchange law for Applicative.
1597	#[quickcheck]
1598	fn applicative_interchange(y: i32) -> bool {
1599		// u <*> pure y = pure ($ y) <*> u
1600		let f = |x: i32| x.wrapping_mul(2);
1601		let u = pure::<OptionBrand, _>(<RcFnBrand as LiftFn>::new(f));
1602
1603		let lhs = apply::<RcFnBrand, OptionBrand, _, _>(u.clone(), pure::<OptionBrand, _>(y));
1604
1605		let rhs_fn = <RcFnBrand as LiftFn>::new(move |f: std::rc::Rc<dyn Fn(i32) -> i32>| f(y));
1606		let rhs = apply::<RcFnBrand, OptionBrand, _, _>(pure::<OptionBrand, _>(rhs_fn), u);
1607
1608		lhs == rhs
1609	}
1610
1611	// Monad Laws
1612
1613	/// Tests the left identity law for Monad.
1614	#[quickcheck]
1615	fn monad_left_identity(a: i32) -> bool {
1616		let f = |x: i32| Some(x.wrapping_mul(2));
1617		explicit::bind::<OptionBrand, _, _, _, _>(pure::<OptionBrand, _>(a), f) == f(a)
1618	}
1619
1620	/// Tests the right identity law for Monad.
1621	#[quickcheck]
1622	fn monad_right_identity(m: Option<i32>) -> bool {
1623		explicit::bind::<OptionBrand, _, _, _, _>(m, pure::<OptionBrand, _>) == m
1624	}
1625
1626	/// Tests the associativity law for Monad.
1627	#[quickcheck]
1628	fn monad_associativity(m: Option<i32>) -> bool {
1629		let f = |x: i32| Some(x.wrapping_mul(2));
1630		let g = |x: i32| Some(x.wrapping_add(1));
1631		explicit::bind::<OptionBrand, _, _, _, _>(
1632			explicit::bind::<OptionBrand, _, _, _, _>(m, f),
1633			g,
1634		) == explicit::bind::<OptionBrand, _, _, _, _>(m, |x| {
1635			explicit::bind::<OptionBrand, _, _, _, _>(f(x), g)
1636		})
1637	}
1638
1639	// Edge Cases
1640
1641	/// Tests `map` on `None`.
1642	#[test]
1643	fn map_none() {
1644		assert_eq!(explicit::map::<OptionBrand, _, _, _, _>(|x: i32| x + 1, None), None);
1645	}
1646
1647	/// Tests `bind` on `None`.
1648	#[test]
1649	fn bind_none() {
1650		assert_eq!(explicit::bind::<OptionBrand, _, _, _, _>(None, |x: i32| Some(x + 1)), None);
1651	}
1652
1653	/// Tests `bind` returning `None`.
1654	#[test]
1655	fn bind_returning_none() {
1656		assert_eq!(explicit::bind::<OptionBrand, _, _, _, _>(Some(5), |_| None::<i32>), None);
1657	}
1658
1659	/// Tests `fold_right` on `None`.
1660	#[test]
1661	fn fold_right_none() {
1662		assert_eq!(
1663			crate::functions::explicit::fold_right::<RcFnBrand, OptionBrand, _, _, _, _>(
1664				|x: i32, acc| x + acc,
1665				0,
1666				None
1667			),
1668			0
1669		);
1670	}
1671
1672	/// Tests `fold_left` on `None`.
1673	#[test]
1674	fn fold_left_none() {
1675		assert_eq!(
1676			crate::functions::explicit::fold_left::<RcFnBrand, OptionBrand, _, _, _, _>(
1677				|acc, x: i32| acc + x,
1678				0,
1679				None
1680			),
1681			0
1682		);
1683	}
1684
1685	/// Tests `traverse` on `None`.
1686	#[test]
1687	fn traverse_none() {
1688		assert_eq!(
1689			crate::classes::traversable::traverse::<OptionBrand, _, _, OptionBrand>(
1690				|x: i32| Some(x + 1),
1691				None
1692			),
1693			Some(None)
1694		);
1695	}
1696
1697	/// Tests `traverse` returning `None`.
1698	#[test]
1699	fn traverse_returning_none() {
1700		assert_eq!(
1701			crate::classes::traversable::traverse::<OptionBrand, _, _, OptionBrand>(
1702				|_: i32| None::<i32>,
1703				Some(5)
1704			),
1705			None
1706		);
1707	}
1708
1709	// MonadRec tests
1710
1711	/// Tests the MonadRec identity law: `tail_rec_m(|a| pure(Done(a)), x) == pure(x)`.
1712	#[quickcheck]
1713	fn monad_rec_identity(x: i32) -> bool {
1714		use {
1715			crate::classes::monad_rec::tail_rec_m,
1716			core::ops::ControlFlow,
1717		};
1718		tail_rec_m::<OptionBrand, _, _>(|a| Some(ControlFlow::Break(a)), x) == Some(x)
1719	}
1720
1721	/// Tests a recursive computation that sums a range via `tail_rec_m`.
1722	#[test]
1723	fn monad_rec_sum_range() {
1724		use {
1725			crate::classes::monad_rec::tail_rec_m,
1726			core::ops::ControlFlow,
1727		};
1728		// Sum 1..=100 using tail_rec_m
1729		let result = tail_rec_m::<OptionBrand, _, _>(
1730			|(n, acc)| {
1731				if n == 0 {
1732					Some(ControlFlow::Break(acc))
1733				} else {
1734					Some(ControlFlow::Continue((n - 1, acc + n)))
1735				}
1736			},
1737			(100i64, 0i64),
1738		);
1739		assert_eq!(result, Some(5050));
1740	}
1741
1742	/// Tests that `tail_rec_m` short-circuits on `None`.
1743	#[test]
1744	fn monad_rec_short_circuit() {
1745		use {
1746			crate::classes::monad_rec::tail_rec_m,
1747			core::ops::ControlFlow,
1748		};
1749		let result: Option<i32> = tail_rec_m::<OptionBrand, _, _>(
1750			|n| {
1751				if n == 5 { None } else { Some(ControlFlow::Continue(n + 1)) }
1752			},
1753			0,
1754		);
1755		assert_eq!(result, None);
1756	}
1757
1758	/// Tests stack safety: `tail_rec_m` handles large iteration counts.
1759	#[test]
1760	fn monad_rec_stack_safety() {
1761		use {
1762			crate::classes::monad_rec::tail_rec_m,
1763			core::ops::ControlFlow,
1764		};
1765		let iterations: i64 = 200_000;
1766		let result = tail_rec_m::<OptionBrand, _, _>(
1767			|acc| {
1768				if acc < iterations {
1769					Some(ControlFlow::Continue(acc + 1))
1770				} else {
1771					Some(ControlFlow::Break(acc))
1772				}
1773			},
1774			0i64,
1775		);
1776		assert_eq!(result, Some(iterations));
1777	}
1778
1779	// RefFunctor Laws
1780
1781	/// Tests the identity law for RefFunctor: `ref_map(|x| *x, opt) == opt`.
1782	#[quickcheck]
1783	fn ref_functor_identity(opt: Option<i32>) -> bool {
1784		use crate::classes::ref_functor::RefFunctor;
1785		OptionBrand::ref_map(|x: &i32| *x, &opt) == opt
1786	}
1787
1788	/// Tests the composition law for RefFunctor.
1789	#[quickcheck]
1790	fn ref_functor_composition(opt: Option<i32>) -> bool {
1791		use crate::classes::ref_functor::RefFunctor;
1792		let f = |x: &i32| x.wrapping_add(1);
1793		let g = |x: &i32| x.wrapping_mul(2);
1794		OptionBrand::ref_map(|x: &i32| f(&g(x)), &opt)
1795			== OptionBrand::ref_map(f, &OptionBrand::ref_map(g, &opt))
1796	}
1797
1798	// RefSemimonad Laws
1799
1800	/// Tests the left identity law for RefSemimonad: `ref_bind(Some(x), |a| Some(*a)) == Some(x)`.
1801	#[quickcheck]
1802	fn ref_semimonad_left_identity(x: i32) -> bool {
1803		use crate::classes::ref_semimonad::RefSemimonad;
1804		OptionBrand::ref_bind(&Some(x), |a: &i32| Some(*a)) == Some(x)
1805	}
1806
1807	// RefFoldable Laws
1808
1809	/// Tests RefFoldable fold_map on Option with Additive monoid.
1810	#[quickcheck]
1811	fn ref_foldable_fold_map(opt: Option<i32>) -> bool {
1812		use crate::{
1813			classes::ref_foldable::RefFoldable,
1814			types::Additive,
1815		};
1816		let result = OptionBrand::ref_fold_map::<RcFnBrand, _, _>(|x: &i32| Additive(*x), &opt);
1817		let expected = match opt {
1818			Some(v) => Additive(v),
1819			None => Additive(0),
1820		};
1821		result == expected
1822	}
1823
1824	// RefSemimonad Laws (continued)
1825
1826	/// Tests the right identity law for RefSemimonad:
1827	/// `ref_bind(m, |a| ref_pure(a)) == m`.
1828	#[quickcheck]
1829	fn ref_semimonad_right_identity(opt: Option<i32>) -> bool {
1830		use crate::classes::{
1831			ref_pointed::RefPointed,
1832			ref_semimonad::RefSemimonad,
1833		};
1834		OptionBrand::ref_bind(&opt, |a: &i32| OptionBrand::ref_pure(a)) == opt
1835	}
1836
1837	/// Tests the associativity law for RefSemimonad.
1838	#[quickcheck]
1839	fn ref_semimonad_associativity(opt: Option<i32>) -> bool {
1840		use crate::classes::ref_semimonad::RefSemimonad;
1841		let f = |a: &i32| if *a > 0 { Some(a.wrapping_mul(2)) } else { None };
1842		let g = |b: &i32| Some(b.wrapping_add(10));
1843		let lhs = OptionBrand::ref_bind(&OptionBrand::ref_bind(&opt, f), g);
1844		let rhs = OptionBrand::ref_bind(&opt, |a: &i32| OptionBrand::ref_bind(&f(a), g));
1845		lhs == rhs
1846	}
1847
1848	// RefLift Laws
1849
1850	/// Tests the identity law for RefLift:
1851	/// `ref_lift2(|_, b| *b, pure(unit), fa) == fa`.
1852	#[quickcheck]
1853	fn ref_lift_identity(opt: Option<i32>) -> bool {
1854		use crate::classes::ref_lift::RefLift;
1855		OptionBrand::ref_lift2(|_: &(), b: &i32| *b, &Some(()), &opt) == opt
1856	}
1857
1858	/// Tests commutativity of ref_lift2 (for Option specifically):
1859	/// `ref_lift2(f, a, b) == ref_lift2(|b, a| f(a, b), b, a)`.
1860	#[quickcheck]
1861	fn ref_lift2_commutativity(
1862		a: Option<i32>,
1863		b: Option<i32>,
1864	) -> bool {
1865		use crate::classes::ref_lift::RefLift;
1866		let lhs = OptionBrand::ref_lift2(|x: &i32, y: &i32| x.wrapping_add(*y), &a, &b);
1867		let rhs = OptionBrand::ref_lift2(|y: &i32, x: &i32| x.wrapping_add(*y), &b, &a);
1868		lhs == rhs
1869	}
1870
1871	// RefTraversable Laws
1872
1873	/// Tests the identity law for RefTraversable:
1874	/// `ref_traverse(|a| Identity(*a), ta) == Identity(ta)`.
1875	#[quickcheck]
1876	fn ref_traversable_identity(opt: Option<i32>) -> bool {
1877		use crate::{
1878			classes::ref_traversable::RefTraversable,
1879			types::Identity,
1880		};
1881		let result: Identity<Option<i32>> =
1882			OptionBrand::ref_traverse::<RcFnBrand, _, _, IdentityBrand>(
1883				|a: &i32| Identity(*a),
1884				&opt,
1885			);
1886		result == Identity(opt)
1887	}
1888
1889	/// Tests RefTraversable naturality: ref_traverse(f, ta) produces
1890	/// the same result as traverse(|a| f(&a), ta).
1891	#[quickcheck]
1892	fn ref_traversable_consistent_with_traverse(opt: Option<i32>) -> bool {
1893		use crate::classes::{
1894			ref_traversable::RefTraversable,
1895			traversable::Traversable,
1896		};
1897		let ref_result: Option<Option<String>> =
1898			OptionBrand::ref_traverse::<RcFnBrand, _, _, OptionBrand>(
1899				|a: &i32| Some(a.to_string()),
1900				&opt,
1901			);
1902		let val_result: Option<Option<String>> =
1903			OptionBrand::traverse::<i32, String, OptionBrand>(|a: i32| Some(a.to_string()), opt);
1904		ref_result == val_result
1905	}
1906
1907	// RefCompactable Laws
1908
1909	/// RefCompactable identity: ref_compact(ref_map(Some, &fa)) == fa.clone()
1910	#[quickcheck]
1911	fn ref_compactable_identity(x: Option<i32>) -> bool {
1912		use crate::classes::ref_compactable::ref_compact;
1913		let mapped: Option<Option<i32>> = x.as_ref().map(|a| Some(*a));
1914		ref_compact::<OptionBrand, _>(&mapped) == x
1915	}
1916
1917	// RefAlt Laws
1918
1919	/// RefAlt associativity
1920	#[quickcheck]
1921	fn ref_alt_associativity(
1922		x: Option<i32>,
1923		y: Option<i32>,
1924		z: Option<i32>,
1925	) -> bool {
1926		use crate::classes::ref_alt::ref_alt;
1927		ref_alt::<OptionBrand, _>(&ref_alt::<OptionBrand, _>(&x, &y), &z)
1928			== ref_alt::<OptionBrand, _>(&x, &ref_alt::<OptionBrand, _>(&y, &z))
1929	}
1930}