#[fp_macros::document_module]
mod inner {
use {
crate::{
Apply,
brands::OptionBrand,
classes::*,
dispatch::Ref,
impl_kind,
kinds::*,
},
core::ops::ControlFlow,
fp_macros::*,
};
impl_kind! {
for OptionBrand {
type Of<'a, A: 'a>: 'a = Option<A>;
}
}
impl Functor for OptionBrand {
#[document_signature]
#[document_type_parameters(
"The lifetime of the value.",
"The type of the value inside the option.",
"The type of the result of applying the function."
)]
#[document_parameters("The function to apply to the value.", "The option to map over.")]
#[document_returns(
"A new option containing the result of applying the function, or `None`."
)]
#[document_examples]
fn map<'a, A: 'a, B: 'a>(
func: impl Fn(A) -> B + 'a,
fa: Apply!(<Self as Kind!( type Of<'a, T: 'a>: 'a; )>::Of<'a, A>),
) -> Apply!(<Self as Kind!( type Of<'a, T: 'a>: 'a; )>::Of<'a, B>) {
fa.map(func)
}
}
impl Lift for OptionBrand {
#[document_signature]
#[document_type_parameters(
"The lifetime of the values.",
"The type of the first option's value.",
"The type of the second option's value.",
"The return type of the function."
)]
#[document_parameters(
"The binary function to apply.",
"The first option.",
"The second option."
)]
#[document_returns("`Some(f(a, b))` if both options are `Some`, otherwise `None`.")]
#[document_examples]
fn lift2<'a, A, B, C>(
func: impl Fn(A, B) -> C + 'a,
fa: Apply!(<Self as Kind!( type Of<'a, T: 'a>: 'a; )>::Of<'a, A>),
fb: Apply!(<Self as Kind!( type Of<'a, T: 'a>: 'a; )>::Of<'a, B>),
) -> Apply!(<Self as Kind!( type Of<'a, T: 'a>: 'a; )>::Of<'a, C>)
where
A: 'a,
B: 'a,
C: 'a, {
fa.zip(fb).map(|(a, b)| func(a, b))
}
}
impl Pointed for OptionBrand {
#[document_signature]
#[document_type_parameters("The lifetime of the value.", "The type of the value to wrap.")]
#[document_parameters("The value to wrap.")]
#[document_returns("`Some(a)`.")]
#[document_examples]
fn pure<'a, A: 'a>(a: A) -> Apply!(<Self as Kind!( type Of<'a, T: 'a>: 'a; )>::Of<'a, A>) {
Some(a)
}
}
impl ApplyFirst for OptionBrand {}
impl ApplySecond for OptionBrand {}
impl Semiapplicative for OptionBrand {
#[document_signature]
#[document_type_parameters(
"The lifetime of the values.",
"The brand of the cloneable function wrapper.",
"The type of the input value.",
"The type of the output value."
)]
#[document_parameters(
"The option containing the function.",
"The option containing the value."
)]
#[document_returns("`Some(f(a))` if both are `Some`, otherwise `None`.")]
#[document_examples]
fn apply<'a, FnBrand: 'a + CloneFn, A: 'a + Clone, B: 'a>(
ff: Apply!(<Self as Kind!( type Of<'a, T: 'a>: 'a; )>::Of<'a, <FnBrand as CloneFn>::Of<'a, A, B>>),
fa: Apply!(<Self as Kind!( type Of<'a, T: 'a>: 'a; )>::Of<'a, A>),
) -> Apply!(<Self as Kind!( type Of<'a, T: 'a>: 'a; )>::Of<'a, B>) {
match (ff, fa) {
(Some(f), Some(a)) => Some(f(a)),
_ => None,
}
}
}
impl Semimonad for OptionBrand {
#[document_signature]
#[document_type_parameters(
"The lifetime of the values.",
"The type of the result of the first computation.",
"The type of the result of the second computation."
)]
#[document_parameters(
"The first option.",
"The function to apply to the value inside the option."
)]
#[document_returns(
"The result of applying `f` to the value if `ma` is `Some`, otherwise `None`."
)]
#[document_examples]
fn bind<'a, A: 'a, B: 'a>(
ma: Apply!(<Self as Kind!( type Of<'a, T: 'a>: 'a; )>::Of<'a, A>),
func: impl Fn(A) -> Apply!(<Self as Kind!( type Of<'a, T: 'a>: 'a; )>::Of<'a, B>) + 'a,
) -> Apply!(<Self as Kind!( type Of<'a, T: 'a>: 'a; )>::Of<'a, B>) {
ma.and_then(func)
}
}
impl Alt for OptionBrand {
#[document_signature]
#[document_type_parameters("The lifetime of the values.", "The type of the value.")]
#[document_parameters("The first option.", "The second option.")]
#[document_returns("The first `Some` value, or `None`.")]
#[document_examples]
fn alt<'a, A: 'a>(
fa1: Apply!(<Self as Kind!( type Of<'a, T: 'a>: 'a; )>::Of<'a, A>),
fa2: Apply!(<Self as Kind!( type Of<'a, T: 'a>: 'a; )>::Of<'a, A>),
) -> Apply!(<Self as Kind!( type Of<'a, T: 'a>: 'a; )>::Of<'a, A>) {
fa1.or(fa2)
}
}
impl RefAlt for OptionBrand {
#[document_signature]
#[document_type_parameters("The lifetime of the values.", "The type of the value.")]
#[document_parameters("The first option.", "The second option.")]
#[document_returns("The first `Some` value (cloned), or `None`.")]
#[document_examples]
fn ref_alt<'a, A: 'a + Clone>(
fa1: &Apply!(<Self as Kind!( type Of<'a, T: 'a>: 'a; )>::Of<'a, A>),
fa2: &Apply!(<Self as Kind!( type Of<'a, T: 'a>: 'a; )>::Of<'a, A>),
) -> Apply!(<Self as Kind!( type Of<'a, T: 'a>: 'a; )>::Of<'a, A>) {
fa1.as_ref().or(fa2.as_ref()).cloned()
}
}
impl Plus for OptionBrand {
#[document_signature]
#[document_type_parameters("The lifetime of the value.", "The type of the value.")]
#[document_returns("`None`.")]
#[document_examples]
fn empty<'a, A: 'a>() -> Apply!(<Self as Kind!( type Of<'a, T: 'a>: 'a; )>::Of<'a, A>) {
None
}
}
impl Foldable for OptionBrand {
#[document_signature]
#[document_type_parameters(
"The lifetime of the values.",
"The brand of the cloneable function to use.",
"The type of the elements in the structure.",
"The type of the accumulator."
)]
#[document_parameters("The folding function.", "The initial value.", "The option to fold.")]
#[document_returns("`func(a, initial)` if `fa` is `Some(a)`, otherwise `initial`.")]
#[document_examples]
fn fold_right<'a, FnBrand, A: 'a + Clone, B: 'a>(
func: impl Fn(A, B) -> B + 'a,
initial: B,
fa: Apply!(<Self as Kind!( type Of<'a, T: 'a>: 'a; )>::Of<'a, A>),
) -> B
where
FnBrand: CloneFn + 'a, {
match fa {
Some(a) => func(a, initial),
None => initial,
}
}
#[document_signature]
#[document_type_parameters(
"The lifetime of the values.",
"The brand of the cloneable function to use.",
"The type of the elements in the structure.",
"The type of the accumulator."
)]
#[document_parameters(
"The function to apply to the accumulator and each element.",
"The initial value of the accumulator.",
"The option to fold."
)]
#[document_returns("`f(initial, a)` if `fa` is `Some(a)`, otherwise `initial`.")]
#[document_examples]
fn fold_left<'a, FnBrand, A: 'a + Clone, B: 'a>(
func: impl Fn(B, A) -> B + 'a,
initial: B,
fa: Apply!(<Self as Kind!( type Of<'a, T: 'a>: 'a; )>::Of<'a, A>),
) -> B
where
FnBrand: CloneFn + 'a, {
match fa {
Some(a) => func(initial, a),
None => initial,
}
}
#[document_signature]
#[document_type_parameters(
"The lifetime of the values.",
"The brand of the cloneable function to use.",
"The type of the elements in the structure.",
"The type of the monoid."
)]
#[document_parameters("The mapping function.", "The option to fold.")]
#[document_returns("`func(a)` if `fa` is `Some(a)`, otherwise `M::empty()`.")]
#[document_examples]
fn fold_map<'a, FnBrand, A: 'a + Clone, M>(
func: impl Fn(A) -> M + 'a,
fa: Apply!(<Self as Kind!( type Of<'a, T: 'a>: 'a; )>::Of<'a, A>),
) -> M
where
M: Monoid + 'a,
FnBrand: CloneFn + 'a, {
match fa {
Some(a) => func(a),
None => M::empty(),
}
}
}
impl Traversable for OptionBrand {
#[document_signature]
#[document_type_parameters(
"The lifetime of the values.",
"The type of the elements in the traversable structure.",
"The type of the elements in the resulting traversable structure.",
"The applicative context."
)]
#[document_parameters(
"The function to apply to each element, returning a value in an applicative context.",
"The option to traverse."
)]
#[document_returns("The option wrapped in the applicative context.")]
#[document_examples]
fn traverse<'a, A: 'a + Clone, B: 'a + Clone, F: Applicative>(
func: impl Fn(A) -> Apply!(<F as Kind!( type Of<'a, T: 'a>: 'a; )>::Of<'a, B>) + 'a,
ta: Apply!(<Self as Kind!( type Of<'a, T: 'a>: 'a; )>::Of<'a, A>),
) -> 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>)>)
where
Apply!(<Self as Kind!( type Of<'a, T: 'a>: 'a; )>::Of<'a, B>): Clone, {
match ta {
Some(a) => F::map(|b| Some(b), func(a)),
None => F::pure(None),
}
}
#[document_signature]
#[document_type_parameters(
"The lifetime of the values.",
"The type of the elements in the traversable structure.",
"The applicative context."
)]
#[document_parameters("The option containing the applicative value.")]
#[document_returns("The result of the traversal.")]
#[document_examples]
fn sequence<'a, A: 'a + Clone, F: Applicative>(
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>)>)
) -> 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>)>)
where
Apply!(<F as Kind!( type Of<'a, T: 'a>: 'a; )>::Of<'a, A>): Clone,
Apply!(<Self as Kind!( type Of<'a, T: 'a>: 'a; )>::Of<'a, A>): Clone, {
match ta {
Some(fa) => F::map(|a| Some(a), fa),
None => F::pure(None),
}
}
}
impl WithIndex for OptionBrand {
type Index = ();
}
impl FunctorWithIndex for OptionBrand {
#[document_signature]
#[document_type_parameters(
"The lifetime of the value.",
"The type of the value inside the option.",
"The type of the result of applying the function."
)]
#[document_parameters(
"The function to apply to the value and its index.",
"The option to map over."
)]
#[document_returns(
"A new option containing the result of applying the function, or `None`."
)]
#[document_examples]
fn map_with_index<'a, A: 'a, B: 'a>(
f: impl Fn((), A) -> B + 'a,
fa: Option<A>,
) -> Option<B> {
fa.map(|a| f((), a))
}
}
impl FoldableWithIndex for OptionBrand {
#[document_signature]
#[document_type_parameters(
"The lifetime of the value.",
"The brand of the cloneable function to use.",
"The type of the value inside the option.",
"The monoid type."
)]
#[document_parameters(
"The function to apply to the value and its index.",
"The option to fold."
)]
#[document_returns("The monoid value.")]
#[document_examples]
fn fold_map_with_index<'a, FnBrand, A: 'a + Clone, R: Monoid + 'a>(
f: impl Fn((), A) -> R + 'a,
fa: Option<A>,
) -> R
where
FnBrand: LiftFn + 'a, {
match fa {
Some(a) => f((), a),
None => R::empty(),
}
}
}
impl TraversableWithIndex for OptionBrand {
#[document_signature]
#[document_type_parameters(
"The lifetime of the value.",
"The type of the value inside the option.",
"The type of the result.",
"The applicative context."
)]
#[document_parameters(
"The function to apply to the value and its index, returning a value in an applicative context.",
"The option to traverse."
)]
#[document_returns("The option wrapped in the applicative context.")]
#[document_examples]
fn traverse_with_index<'a, A: 'a, B: 'a + Clone, M: Applicative>(
f: impl Fn((), A) -> M::Of<'a, B> + 'a,
ta: Option<A>,
) -> M::Of<'a, Option<B>> {
match ta {
Some(a) => M::map(|b| Some(b), f((), a)),
None => M::pure(None),
}
}
}
impl Compactable for OptionBrand {
#[document_signature]
#[document_type_parameters("The lifetime of the values.", "The type of the elements.")]
#[document_parameters("The nested option.")]
#[document_returns("The flattened option.")]
#[document_examples]
fn compact<'a, A: 'a>(
fa: Apply!(<Self as Kind!( type Of<'a, T: 'a>: 'a; )>::Of<
'a,
Apply!(<OptionBrand as Kind!( type Of<'a, T: 'a>: 'a; )>::Of<'a, A>),
>)
) -> Apply!(<Self as Kind!( type Of<'a, T: 'a>: 'a; )>::Of<'a, A>) {
fa.flatten()
}
#[document_signature]
#[document_type_parameters(
"The lifetime of the values.",
"The type of the error value.",
"The type of the success value."
)]
#[document_parameters("The option of result.")]
#[document_returns("A pair of options.")]
#[document_examples]
fn separate<'a, E: 'a, O: 'a>(
fa: Apply!(<Self as Kind!( type Of<'a, T: 'a>: 'a; )>::Of<'a, Result<O, E>>)
) -> (
Apply!(<Self as Kind!( type Of<'a, T: 'a>: 'a; )>::Of<'a, E>),
Apply!(<Self as Kind!( type Of<'a, T: 'a>: 'a; )>::Of<'a, O>),
) {
match fa {
Some(Ok(o)) => (None, Some(o)),
Some(Err(e)) => (Some(e), None),
None => (None, None),
}
}
}
impl RefCompactable for OptionBrand {
#[document_signature]
#[document_type_parameters(
"The lifetime of the values.",
"The type of the elements. Must be [`Clone`] because elements are extracted from a borrowed container."
)]
#[document_parameters("A reference to the nested option.")]
#[document_returns("The flattened option with the inner value cloned, or [`None`].")]
#[document_examples]
fn ref_compact<'a, A: 'a + Clone>(
fa: &Apply!(<Self as Kind!( type Of<'a, T: 'a>: 'a; )>::Of<'a, Option<A>>)
) -> Apply!(<Self as Kind!( type Of<'a, T: 'a>: 'a; )>::Of<'a, A>) {
match fa {
Some(Some(a)) => Some(a.clone()),
_ => None,
}
}
#[document_signature]
#[document_type_parameters(
"The lifetime of the values.",
"The type of the error value. Must be [`Clone`] because elements are extracted from a borrowed container.",
"The type of the success value. Must be [`Clone`] because elements are extracted from a borrowed container."
)]
#[document_parameters("A reference to the option of result.")]
#[document_returns(
"A pair of options: the first containing the cloned error, the second containing the cloned success value."
)]
#[document_examples]
fn ref_separate<'a, E: 'a + Clone, O: 'a + Clone>(
fa: &Apply!(<Self as Kind!( type Of<'a, T: 'a>: 'a; )>::Of<'a, Result<O, E>>)
) -> (
Apply!(<Self as Kind!( type Of<'a, T: 'a>: 'a; )>::Of<'a, E>),
Apply!(<Self as Kind!( type Of<'a, T: 'a>: 'a; )>::Of<'a, O>),
) {
match fa {
Some(Ok(o)) => (None, Some(o.clone())),
Some(Err(e)) => (Some(e.clone()), None),
None => (None, None),
}
}
}
impl Filterable for OptionBrand {
#[document_signature]
#[document_type_parameters(
"The lifetime of the values.",
"The type of the input value.",
"The type of the error value.",
"The type of the success value."
)]
#[document_parameters("The function to apply.", "The option to partition.")]
#[document_returns("A pair of options.")]
#[document_examples]
fn partition_map<'a, A: 'a, E: 'a, O: 'a>(
func: impl Fn(A) -> Result<O, E> + 'a,
fa: Apply!(<Self as Kind!( type Of<'a, T: 'a>: 'a; )>::Of<'a, A>),
) -> (
Apply!(<Self as Kind!( type Of<'a, T: 'a>: 'a; )>::Of<'a, E>),
Apply!(<Self as Kind!( type Of<'a, T: 'a>: 'a; )>::Of<'a, O>),
) {
match fa {
Some(a) => match func(a) {
Ok(o) => (None, Some(o)),
Err(e) => (Some(e), None),
},
None => (None, None),
}
}
#[document_signature]
#[document_type_parameters("The lifetime of the values.", "The type of the elements.")]
#[document_parameters("The predicate.", "The option to partition.")]
#[document_returns("A pair of options.")]
#[document_examples]
fn partition<'a, A: 'a + Clone>(
func: impl Fn(A) -> bool + 'a,
fa: Apply!(<Self as Kind!( type Of<'a, T: 'a>: 'a; )>::Of<'a, A>),
) -> (
Apply!(<Self as Kind!( type Of<'a, T: 'a>: 'a; )>::Of<'a, A>),
Apply!(<Self as Kind!( type Of<'a, T: 'a>: 'a; )>::Of<'a, A>),
) {
match fa {
Some(a) =>
if func(a.clone()) {
(None, Some(a))
} else {
(Some(a), None)
},
None => (None, None),
}
}
#[document_signature]
#[document_type_parameters(
"The lifetime of the values.",
"The type of the input value.",
"The type of the result of applying the function."
)]
#[document_parameters("The function to apply.", "The option to filter and map.")]
#[document_returns("The filtered and mapped option.")]
#[document_examples]
fn filter_map<'a, A: 'a, B: 'a>(
func: impl Fn(A) -> Option<B> + 'a,
fa: Apply!(<Self as Kind!( type Of<'a, T: 'a>: 'a; )>::Of<'a, A>),
) -> Apply!(<Self as Kind!( type Of<'a, T: 'a>: 'a; )>::Of<'a, B>) {
fa.and_then(func)
}
#[document_signature]
#[document_type_parameters("The lifetime of the values.", "The type of the elements.")]
#[document_parameters("The predicate.", "The option to filter.")]
#[document_returns("The filtered option.")]
#[document_examples]
fn filter<'a, A: 'a + Clone>(
func: impl Fn(A) -> bool + 'a,
fa: Apply!(<Self as Kind!( type Of<'a, T: 'a>: 'a; )>::Of<'a, A>),
) -> Apply!(<Self as Kind!( type Of<'a, T: 'a>: 'a; )>::Of<'a, A>) {
fa.filter(|a| func(a.clone()))
}
}
impl Witherable for OptionBrand {
#[document_signature]
#[document_type_parameters(
"The lifetime of the values.",
"The applicative context.",
"The type of the elements in the input structure.",
"The type of the error values.",
"The type of the success values."
)]
#[document_parameters(
"The function to apply to each element, returning a `Result` in an applicative context.",
"The option to partition."
)]
#[document_returns("The partitioned option wrapped in the applicative context.")]
#[document_examples]
fn wilt<'a, M: Applicative, A: 'a + Clone, E: 'a + Clone, O: 'a + Clone>(
func: impl Fn(A) -> Apply!(<M as Kind!( type Of<'a, T: 'a>: 'a; )>::Of<'a, Result<O, E>>)
+ 'a,
ta: Apply!(<Self as Kind!( type Of<'a, T: 'a>: 'a; )>::Of<'a, A>),
) -> Apply!(<M as Kind!( type Of<'a, T: 'a>: 'a; )>::Of<
'a,
(
Apply!(<Self as Kind!( type Of<'a, T: 'a>: 'a; )>::Of<'a, E>),
Apply!(<Self as Kind!( type Of<'a, T: 'a>: 'a; )>::Of<'a, O>),
),
>)
where
Apply!(<Self as Kind!( type Of<'a, T: 'a>: 'a; )>::Of<'a, Result<O, E>>): Clone,
Apply!(<M as Kind!( type Of<'a, T: 'a>: 'a; )>::Of<'a, Result<O, E>>): Clone, {
match ta {
Some(a) => M::map(
|res| match res {
Ok(o) => (None, Some(o)),
Err(e) => (Some(e), None),
},
func(a),
),
None => M::pure((None, None)),
}
}
#[document_signature]
#[document_type_parameters(
"The lifetime of the values.",
"The applicative context.",
"The type of the elements in the input structure.",
"The type of the result of applying the function."
)]
#[document_parameters(
"The function to apply to each element, returning an `Option` in an applicative context.",
"The option to filter and map."
)]
#[document_returns("The filtered and mapped option wrapped in the applicative context.")]
#[document_examples]
fn wither<'a, M: Applicative, A: 'a + Clone, B: 'a + Clone>(
func: impl Fn(A) -> Apply!(<M as Kind!( type Of<'a, T: 'a>: 'a; )>::Of<'a, Option<B>>) + 'a,
ta: Apply!(<Self as Kind!( type Of<'a, T: 'a>: 'a; )>::Of<'a, A>),
) -> 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>),
>)
where
Apply!(<Self as Kind!( type Of<'a, T: 'a>: 'a; )>::Of<'a, Option<B>>): Clone,
Apply!(<M as Kind!( type Of<'a, T: 'a>: 'a; )>::Of<'a, Option<B>>): Clone, {
match ta {
Some(a) => func(a),
None => M::pure(None),
}
}
}
impl MonadRec for OptionBrand {
#[document_signature]
#[document_type_parameters(
"The lifetime of the computation.",
"The type of the initial value and loop state.",
"The type of the result."
)]
#[document_parameters("The step function.", "The initial value.")]
#[document_returns(
"The result of the computation, or `None` if the step function returned `None`."
)]
#[document_examples]
fn tail_rec_m<'a, A: 'a, B: 'a>(
func: impl Fn(
A,
)
-> Apply!(<Self as Kind!( type Of<'a, T: 'a>: 'a; )>::Of<'a, ControlFlow<B, A>>)
+ 'a,
initial: A,
) -> Apply!(<Self as Kind!( type Of<'a, T: 'a>: 'a; )>::Of<'a, B>) {
let mut current = initial;
loop {
match func(current) {
None => return None,
Some(ControlFlow::Continue(next)) => current = next,
Some(ControlFlow::Break(b)) => return Some(b),
}
}
}
}
impl RefFunctor for OptionBrand {
#[document_signature]
#[document_type_parameters("The lifetime.", "The input type.", "The output type.")]
#[document_parameters("The function.", "The option.")]
#[document_returns("The mapped option.")]
#[document_examples]
fn ref_map<'a, A: 'a, B: 'a>(
func: impl Fn(&A) -> B + 'a,
fa: &Apply!(<Self as Kind!( type Of<'a, T: 'a>: 'a; )>::Of<'a, A>),
) -> Apply!(<Self as Kind!( type Of<'a, T: 'a>: 'a; )>::Of<'a, B>) {
fa.as_ref().map(func)
}
}
impl RefFoldable for OptionBrand {
#[document_signature]
#[document_type_parameters(
"The lifetime.",
"The brand.",
"The element type.",
"The monoid type."
)]
#[document_parameters("The mapping function.", "The option.")]
#[document_returns("The monoid value.")]
#[document_examples]
fn ref_fold_map<'a, FnBrand, A: 'a + Clone, M>(
func: impl Fn(&A) -> M + 'a,
fa: &Apply!(<Self as Kind!( type Of<'a, T: 'a>: 'a; )>::Of<'a, A>),
) -> M
where
FnBrand: LiftFn + 'a,
M: Monoid + 'a, {
match fa {
Some(a) => func(a),
None => Monoid::empty(),
}
}
}
impl RefFilterable for OptionBrand {
#[document_signature]
#[document_type_parameters("The lifetime.", "The input type.", "The output type.")]
#[document_parameters("The function.", "The option.")]
#[document_returns("The filtered option.")]
#[document_examples]
fn ref_filter_map<'a, A: 'a, B: 'a>(
func: impl Fn(&A) -> Option<B> + 'a,
fa: &Apply!(<Self as Kind!( type Of<'a, T: 'a>: 'a; )>::Of<'a, A>),
) -> Apply!(<Self as Kind!( type Of<'a, T: 'a>: 'a; )>::Of<'a, B>) {
fa.as_ref().and_then(func)
}
}
impl RefTraversable for OptionBrand {
#[document_signature]
#[document_type_parameters(
"The lifetime.",
"The brand.",
"The input type.",
"The output type.",
"The applicative."
)]
#[document_parameters("The function.", "The option.")]
#[document_returns("The traversed result.")]
#[document_examples]
fn ref_traverse<'a, FnBrand, A: 'a + Clone, B: 'a + Clone, F: Applicative>(
func: impl Fn(&A) -> Apply!(<F as Kind!( type Of<'a, T: 'a>: 'a; )>::Of<'a, B>) + 'a,
ta: &Apply!(<Self as Kind!( type Of<'a, T: 'a>: 'a; )>::Of<'a, A>),
) -> 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>)>)
where
FnBrand: LiftFn + 'a,
Apply!(<Self as Kind!( type Of<'a, T: 'a>: 'a; )>::Of<'a, B>): Clone,
Apply!(<F as Kind!( type Of<'a, T: 'a>: 'a; )>::Of<'a, B>): Clone, {
match ta {
Some(a) => F::map(|b| Some(b), func(a)),
None => F::pure(None),
}
}
}
impl RefWitherable for OptionBrand {}
impl RefFunctorWithIndex for OptionBrand {
#[document_signature]
#[document_type_parameters("The lifetime.", "The input type.", "The output type.")]
#[document_parameters("The function.", "The option.")]
#[document_returns("The mapped option.")]
#[document_examples]
fn ref_map_with_index<'a, A: 'a, B: 'a>(
func: impl Fn((), &A) -> B + 'a,
fa: &Apply!(<Self as Kind!( type Of<'a, T: 'a>: 'a; )>::Of<'a, A>),
) -> Apply!(<Self as Kind!( type Of<'a, T: 'a>: 'a; )>::Of<'a, B>) {
fa.as_ref().map(|a| func((), a))
}
}
impl RefFoldableWithIndex for OptionBrand {
#[document_signature]
#[document_type_parameters(
"The lifetime.",
"The brand of the cloneable function.",
"The element type.",
"The monoid type."
)]
#[document_parameters("The function.", "The option.")]
#[document_returns("The monoid value.")]
#[document_examples]
fn ref_fold_map_with_index<'a, FnBrand, A: 'a + Clone, R: Monoid + 'a>(
func: impl Fn((), &A) -> R + 'a,
fa: &Apply!(<Self as Kind!( type Of<'a, T: 'a>: 'a; )>::Of<'a, A>),
) -> R
where
FnBrand: LiftFn + 'a, {
match fa {
Some(a) => func((), a),
None => Monoid::empty(),
}
}
}
impl RefTraversableWithIndex for OptionBrand {
#[document_signature]
#[document_type_parameters(
"The lifetime.",
"The input type.",
"The output type.",
"The applicative."
)]
#[document_parameters("The function.", "The option.")]
#[document_returns("The traversed result.")]
#[document_examples]
fn ref_traverse_with_index<'a, A: 'a + Clone, B: 'a + Clone, M: Applicative>(
f: impl Fn((), &A) -> Apply!(<M as Kind!( type Of<'a, T: 'a>: 'a; )>::Of<'a, B>) + 'a,
ta: &Apply!(<Self as Kind!( type Of<'a, T: 'a>: 'a; )>::Of<'a, A>),
) -> 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>)>)
where
Apply!(<Self as Kind!( type Of<'a, T: 'a>: 'a; )>::Of<'a, B>): Clone,
Apply!(<M as Kind!( type Of<'a, T: 'a>: 'a; )>::Of<'a, B>): Clone, {
match ta {
Some(a) => M::map(|b| Some(b), f((), a)),
None => M::pure(None),
}
}
}
impl RefPointed for OptionBrand {
#[document_signature]
#[document_type_parameters("The lifetime of the value.", "The type of the value.")]
#[document_parameters("The reference to the value to wrap.")]
#[document_returns("A `Some` containing a clone of the value.")]
#[document_examples]
fn ref_pure<'a, A: Clone + 'a>(
a: &A
) -> Apply!(<Self as Kind!( type Of<'a, T: 'a>: 'a; )>::Of<'a, A>) {
Some(a.clone())
}
}
impl RefLift for OptionBrand {
#[document_signature]
#[document_type_parameters(
"The lifetime.",
"First input type.",
"Second input type.",
"Output type."
)]
#[document_parameters("The binary function.", "The first option.", "The second option.")]
#[document_returns("The combined result, or `None` if either input is `None`.")]
#[document_examples]
fn ref_lift2<'a, A: 'a, B: 'a, C: 'a>(
func: impl Fn(&A, &B) -> C + 'a,
fa: &Apply!(<Self as Kind!( type Of<'a, T: 'a>: 'a; )>::Of<'a, A>),
fb: &Apply!(<Self as Kind!( type Of<'a, T: 'a>: 'a; )>::Of<'a, B>),
) -> Apply!(<Self as Kind!( type Of<'a, T: 'a>: 'a; )>::Of<'a, C>) {
match (fa.as_ref(), fb.as_ref()) {
(Some(a), Some(b)) => Some(func(a, b)),
_ => None,
}
}
}
impl RefSemiapplicative for OptionBrand {
#[document_signature]
#[document_type_parameters(
"The lifetime.",
"The function brand.",
"The input type.",
"The output type."
)]
#[document_parameters(
"The option containing the by-ref function.",
"The option containing the value."
)]
#[document_returns("The result of applying the function, or `None`.")]
#[document_examples]
fn ref_apply<'a, FnBrand: 'a + CloneFn<Ref>, A: 'a, B: 'a>(
ff: &Apply!(<Self as Kind!( type Of<'a, T: 'a>: 'a; )>::Of<'a, <FnBrand as CloneFn<Ref>>::Of<'a, A, B>>),
fa: &Apply!(<Self as Kind!( type Of<'a, T: 'a>: 'a; )>::Of<'a, A>),
) -> Apply!(<Self as Kind!( type Of<'a, T: 'a>: 'a; )>::Of<'a, B>) {
match (ff, fa.as_ref()) {
(Some(f), Some(a)) => Some((**f)(a)),
_ => None,
}
}
}
impl RefSemimonad for OptionBrand {
#[document_signature]
#[document_type_parameters("The lifetime.", "The input type.", "The output type.")]
#[document_parameters("The input option.", "The function to apply by reference.")]
#[document_returns("The result of applying the function, or `None`.")]
#[document_examples]
fn ref_bind<'a, A: 'a, B: 'a>(
fa: &Apply!(<Self as Kind!( type Of<'a, T: 'a>: 'a; )>::Of<'a, A>),
f: impl Fn(&A) -> Apply!(<Self as Kind!( type Of<'a, T: 'a>: 'a; )>::Of<'a, B>) + 'a,
) -> Apply!(<Self as Kind!( type Of<'a, T: 'a>: 'a; )>::Of<'a, B>) {
fa.as_ref().and_then(f)
}
}
}
#[cfg(test)]
mod tests {
use {
crate::{
brands::*,
classes::*,
functions::*,
},
quickcheck_macros::quickcheck,
};
#[quickcheck]
fn functor_identity(x: Option<i32>) -> bool {
explicit::map::<OptionBrand, _, _, _, _>(identity, x) == x
}
#[quickcheck]
fn functor_composition(x: Option<i32>) -> bool {
let f = |x: i32| x.wrapping_add(1);
let g = |x: i32| x.wrapping_mul(2);
explicit::map::<OptionBrand, _, _, _, _>(compose(f, g), x)
== explicit::map::<OptionBrand, _, _, _, _>(
f,
explicit::map::<OptionBrand, _, _, _, _>(g, x),
)
}
#[quickcheck]
fn applicative_identity(v: Option<i32>) -> bool {
apply(pure::<OptionBrand, _>(<RcFnBrand as LiftFn>::new(identity)), v) == v
}
#[quickcheck]
fn applicative_homomorphism(x: i32) -> bool {
let f = |x: i32| x.wrapping_mul(2);
apply(pure::<OptionBrand, _>(<RcFnBrand as LiftFn>::new(f)), pure::<OptionBrand, _>(x))
== pure::<OptionBrand, _>(f(x))
}
#[quickcheck]
fn applicative_composition(
w: Option<i32>,
u_is_some: bool,
v_is_some: bool,
) -> bool {
let v_fn = |x: i32| x.wrapping_mul(2);
let u_fn = |x: i32| x.wrapping_add(1);
let v =
if v_is_some { pure::<OptionBrand, _>(<RcFnBrand as LiftFn>::new(v_fn)) } else { None };
let u =
if u_is_some { pure::<OptionBrand, _>(<RcFnBrand as LiftFn>::new(u_fn)) } else { None };
let vw = apply(v.clone(), w);
let rhs = apply(u.clone(), vw);
let uv = match (u, v) {
(Some(uf), Some(vf)) => {
let composed = move |x| uf(vf(x));
Some(<RcFnBrand as LiftFn>::new(composed))
}
_ => None,
};
let lhs = apply(uv, w);
lhs == rhs
}
#[quickcheck]
fn applicative_interchange(y: i32) -> bool {
let f = |x: i32| x.wrapping_mul(2);
let u = pure::<OptionBrand, _>(<RcFnBrand as LiftFn>::new(f));
let lhs = apply(u.clone(), pure::<OptionBrand, _>(y));
let rhs_fn = <RcFnBrand as LiftFn>::new(move |f: std::rc::Rc<dyn Fn(i32) -> i32>| f(y));
let rhs = apply(pure::<OptionBrand, _>(rhs_fn), u);
lhs == rhs
}
#[quickcheck]
fn monad_left_identity(a: i32) -> bool {
let f = |x: i32| Some(x.wrapping_mul(2));
explicit::bind::<OptionBrand, _, _, _, _>(pure::<OptionBrand, _>(a), f) == f(a)
}
#[quickcheck]
fn monad_right_identity(m: Option<i32>) -> bool {
explicit::bind::<OptionBrand, _, _, _, _>(m, pure::<OptionBrand, _>) == m
}
#[quickcheck]
fn monad_associativity(m: Option<i32>) -> bool {
let f = |x: i32| Some(x.wrapping_mul(2));
let g = |x: i32| Some(x.wrapping_add(1));
explicit::bind::<OptionBrand, _, _, _, _>(
explicit::bind::<OptionBrand, _, _, _, _>(m, f),
g,
) == explicit::bind::<OptionBrand, _, _, _, _>(m, |x| {
explicit::bind::<OptionBrand, _, _, _, _>(f(x), g)
})
}
#[test]
fn map_none() {
assert_eq!(explicit::map::<OptionBrand, _, _, _, _>(|x: i32| x + 1, None), None);
}
#[test]
fn bind_none() {
assert_eq!(explicit::bind::<OptionBrand, _, _, _, _>(None, |x: i32| Some(x + 1)), None);
}
#[test]
fn bind_returning_none() {
assert_eq!(explicit::bind::<OptionBrand, _, _, _, _>(Some(5), |_| None::<i32>), None);
}
#[test]
fn fold_right_none() {
assert_eq!(
crate::functions::explicit::fold_right::<RcFnBrand, OptionBrand, _, _, _, _>(
|x: i32, acc| x + acc,
0,
None
),
0
);
}
#[test]
fn fold_left_none() {
assert_eq!(
crate::functions::explicit::fold_left::<RcFnBrand, OptionBrand, _, _, _, _>(
|acc, x: i32| acc + x,
0,
None
),
0
);
}
#[test]
fn traverse_none() {
assert_eq!(
crate::classes::traversable::traverse::<OptionBrand, _, _, OptionBrand>(
|x: i32| Some(x + 1),
None
),
Some(None)
);
}
#[test]
fn traverse_returning_none() {
assert_eq!(
crate::classes::traversable::traverse::<OptionBrand, _, _, OptionBrand>(
|_: i32| None::<i32>,
Some(5)
),
None
);
}
#[quickcheck]
fn monad_rec_identity(x: i32) -> bool {
use {
crate::classes::monad_rec::tail_rec_m,
core::ops::ControlFlow,
};
tail_rec_m::<OptionBrand, _, _>(|a| Some(ControlFlow::Break(a)), x) == Some(x)
}
#[test]
fn monad_rec_sum_range() {
use {
crate::classes::monad_rec::tail_rec_m,
core::ops::ControlFlow,
};
let result = tail_rec_m::<OptionBrand, _, _>(
|(n, acc)| {
if n == 0 {
Some(ControlFlow::Break(acc))
} else {
Some(ControlFlow::Continue((n - 1, acc + n)))
}
},
(100i64, 0i64),
);
assert_eq!(result, Some(5050));
}
#[test]
fn monad_rec_short_circuit() {
use {
crate::classes::monad_rec::tail_rec_m,
core::ops::ControlFlow,
};
let result: Option<i32> = tail_rec_m::<OptionBrand, _, _>(
|n| {
if n == 5 { None } else { Some(ControlFlow::Continue(n + 1)) }
},
0,
);
assert_eq!(result, None);
}
#[test]
fn monad_rec_stack_safety() {
use {
crate::classes::monad_rec::tail_rec_m,
core::ops::ControlFlow,
};
let iterations: i64 = 200_000;
let result = tail_rec_m::<OptionBrand, _, _>(
|acc| {
if acc < iterations {
Some(ControlFlow::Continue(acc + 1))
} else {
Some(ControlFlow::Break(acc))
}
},
0i64,
);
assert_eq!(result, Some(iterations));
}
#[quickcheck]
fn ref_functor_identity(opt: Option<i32>) -> bool {
use crate::classes::ref_functor::RefFunctor;
OptionBrand::ref_map(|x: &i32| *x, &opt) == opt
}
#[quickcheck]
fn ref_functor_composition(opt: Option<i32>) -> bool {
use crate::classes::ref_functor::RefFunctor;
let f = |x: &i32| x.wrapping_add(1);
let g = |x: &i32| x.wrapping_mul(2);
OptionBrand::ref_map(|x: &i32| f(&g(x)), &opt)
== OptionBrand::ref_map(f, &OptionBrand::ref_map(g, &opt))
}
#[quickcheck]
fn ref_semimonad_left_identity(x: i32) -> bool {
use crate::classes::ref_semimonad::RefSemimonad;
OptionBrand::ref_bind(&Some(x), |a: &i32| Some(*a)) == Some(x)
}
#[quickcheck]
fn ref_foldable_fold_map(opt: Option<i32>) -> bool {
use crate::{
classes::ref_foldable::RefFoldable,
types::Additive,
};
let result = OptionBrand::ref_fold_map::<RcFnBrand, _, _>(|x: &i32| Additive(*x), &opt);
let expected = match opt {
Some(v) => Additive(v),
None => Additive(0),
};
result == expected
}
#[quickcheck]
fn ref_semimonad_right_identity(opt: Option<i32>) -> bool {
use crate::classes::{
ref_pointed::RefPointed,
ref_semimonad::RefSemimonad,
};
OptionBrand::ref_bind(&opt, |a: &i32| OptionBrand::ref_pure(a)) == opt
}
#[quickcheck]
fn ref_semimonad_associativity(opt: Option<i32>) -> bool {
use crate::classes::ref_semimonad::RefSemimonad;
let f = |a: &i32| if *a > 0 { Some(a.wrapping_mul(2)) } else { None };
let g = |b: &i32| Some(b.wrapping_add(10));
let lhs = OptionBrand::ref_bind(&OptionBrand::ref_bind(&opt, f), g);
let rhs = OptionBrand::ref_bind(&opt, |a: &i32| OptionBrand::ref_bind(&f(a), g));
lhs == rhs
}
#[quickcheck]
fn ref_lift_identity(opt: Option<i32>) -> bool {
use crate::classes::ref_lift::RefLift;
OptionBrand::ref_lift2(|_: &(), b: &i32| *b, &Some(()), &opt) == opt
}
#[quickcheck]
fn ref_lift2_commutativity(
a: Option<i32>,
b: Option<i32>,
) -> bool {
use crate::classes::ref_lift::RefLift;
let lhs = OptionBrand::ref_lift2(|x: &i32, y: &i32| x.wrapping_add(*y), &a, &b);
let rhs = OptionBrand::ref_lift2(|y: &i32, x: &i32| x.wrapping_add(*y), &b, &a);
lhs == rhs
}
#[quickcheck]
fn ref_traversable_identity(opt: Option<i32>) -> bool {
use crate::{
classes::ref_traversable::RefTraversable,
types::Identity,
};
let result: Identity<Option<i32>> =
OptionBrand::ref_traverse::<RcFnBrand, _, _, IdentityBrand>(
|a: &i32| Identity(*a),
&opt,
);
result == Identity(opt)
}
#[quickcheck]
fn ref_traversable_consistent_with_traverse(opt: Option<i32>) -> bool {
use crate::classes::{
ref_traversable::RefTraversable,
traversable::Traversable,
};
let ref_result: Option<Option<String>> =
OptionBrand::ref_traverse::<RcFnBrand, _, _, OptionBrand>(
|a: &i32| Some(a.to_string()),
&opt,
);
let val_result: Option<Option<String>> =
OptionBrand::traverse::<i32, String, OptionBrand>(|a: i32| Some(a.to_string()), opt);
ref_result == val_result
}
#[quickcheck]
fn ref_compactable_identity(x: Option<i32>) -> bool {
use crate::classes::ref_compactable::ref_compact;
let mapped: Option<Option<i32>> = x.as_ref().map(|a| Some(*a));
ref_compact::<OptionBrand, _>(&mapped) == x
}
#[quickcheck]
fn ref_alt_associativity(
x: Option<i32>,
y: Option<i32>,
z: Option<i32>,
) -> bool {
use crate::classes::ref_alt::ref_alt;
ref_alt::<OptionBrand, _>(&ref_alt::<OptionBrand, _>(&x, &y), &z)
== ref_alt::<OptionBrand, _>(&x, &ref_alt::<OptionBrand, _>(&y, &z))
}
}