#[fp_macros::document_module]
mod inner {
use {
crate::{
Apply,
brands::{
OptionBrand,
VecBrand,
},
classes::{
Alt,
Applicative,
ApplyFirst,
ApplySecond,
CloneableFn,
Compactable,
Extend,
Filterable,
Foldable,
Functor,
Lift,
MonadRec,
Monoid,
ParCompactable,
ParFilterable,
ParFoldable,
ParFunctor,
Plus,
Pointed,
Semiapplicative,
Semigroup,
Semimonad,
Traversable,
Witherable,
foldable_with_index::FoldableWithIndex,
functor_with_index::FunctorWithIndex,
par_foldable_with_index::ParFoldableWithIndex,
par_functor_with_index::ParFunctorWithIndex,
traversable_with_index::TraversableWithIndex,
with_index::WithIndex,
},
impl_kind,
kinds::*,
},
core::ops::ControlFlow,
fp_macros::*,
};
impl_kind! {
for VecBrand {
type Of<'a, A: 'a>: 'a = Vec<A>;
}
}
impl VecBrand {
#[document_signature]
#[document_type_parameters("The type of the elements in the vector.")]
#[document_parameters(
"A value to prepend to the vector.",
"A vector to prepend the value to."
)]
#[document_returns(
"A new vector consisting of the `head` element prepended to the `tail` vector."
)]
#[document_examples]
pub fn construct<A>(
head: A,
tail: Vec<A>,
) -> Vec<A>
where
A: Clone, {
[vec![head], tail].concat()
}
#[document_signature]
#[document_type_parameters("The type of the elements in the vector.")]
#[document_parameters("The vector slice to deconstruct.")]
#[document_returns(
"An [`Option`] containing a tuple of the head element and the remaining tail vector, or [`None`] if the slice is empty."
)]
#[document_examples]
pub fn deconstruct<A>(slice: &[A]) -> Option<(A, Vec<A>)>
where
A: Clone, {
match slice {
[] => None,
[head, tail @ ..] => Some((head.clone(), tail.to_vec())),
}
}
}
impl Functor for VecBrand {
#[document_signature]
#[document_type_parameters(
"The lifetime of the elements.",
"The type of the elements in the vector.",
"The type of the elements in the resulting vector."
)]
#[document_parameters("The function to apply to each element.", "The vector to map over.")]
#[document_returns("A new vector containing the results of applying the function.")]
#[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.into_iter().map(func).collect()
}
}
impl Lift for VecBrand {
#[document_signature]
#[document_type_parameters(
"The lifetime of the elements.",
"The type of the elements in the first vector.",
"The type of the elements in the second vector.",
"The type of the elements in the resulting vector."
)]
#[document_parameters(
"The binary function to apply.",
"The first vector.",
"The second vector."
)]
#[document_returns(
"A new vector containing the results of applying the function to all pairs of elements."
)]
#[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: Clone + 'a,
B: Clone + 'a,
C: 'a, {
fa.iter().flat_map(|a| fb.iter().map(|b| func(a.clone(), b.clone()))).collect()
}
}
impl Pointed for VecBrand {
#[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("A vector containing the single value.")]
#[document_examples]
fn pure<'a, A: 'a>(a: A) -> Apply!(<Self as Kind!( type Of<'a, T: 'a>: 'a; )>::Of<'a, A>) {
vec![a]
}
}
impl ApplyFirst for VecBrand {}
impl ApplySecond for VecBrand {}
impl Semiapplicative for VecBrand {
#[document_signature]
#[document_type_parameters(
"The lifetime of the values.",
"The brand of the cloneable function wrapper.",
"The type of the input values.",
"The type of the output values."
)]
#[document_parameters(
"The vector containing the functions.",
"The vector containing the values."
)]
#[document_returns(
"A new vector containing the results of applying each function to each value."
)]
#[document_examples]
fn apply<'a, FnBrand: 'a + CloneableFn, A: 'a + Clone, B: 'a>(
ff: Apply!(<Self as Kind!( type Of<'a, T: 'a>: 'a; )>::Of<'a, <FnBrand as CloneableFn>::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>) {
ff.iter().flat_map(|f| fa.iter().map(move |a| f(a.clone()))).collect()
}
}
impl Semimonad for VecBrand {
#[document_signature]
#[document_type_parameters(
"The lifetime of the elements.",
"The type of the elements in the input vector.",
"The type of the elements in the output vector."
)]
#[document_parameters(
"The first vector.",
"The function to apply to each element, returning a vector."
)]
#[document_returns("A new vector containing the flattened results.")]
#[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.into_iter().flat_map(func).collect()
}
}
impl Alt for VecBrand {
#[document_signature]
#[document_type_parameters("The lifetime of the elements.", "The type of the elements.")]
#[document_parameters("The first vector.", "The second vector.")]
#[document_returns("The concatenated vector.")]
#[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>) {
let mut result = fa1;
result.extend(fa2);
result
}
}
impl Plus for VecBrand {
#[document_signature]
#[document_type_parameters("The lifetime of the elements.", "The type of the elements.")]
#[document_returns("An empty vector.")]
#[document_examples]
fn empty<'a, A: 'a>() -> Apply!(<Self as Kind!( type Of<'a, T: 'a>: 'a; )>::Of<'a, A>) {
Vec::new()
}
}
impl Foldable for VecBrand {
#[document_signature]
#[document_type_parameters(
"The lifetime of the elements.",
"The brand of the cloneable function to use.",
"The type of the elements in the vector.",
"The type of the accumulator."
)]
#[document_parameters("The folding function.", "The initial value.", "The vector to fold.")]
#[document_returns("The final accumulator value.")]
#[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: CloneableFn + 'a, {
fa.into_iter().rev().fold(initial, |acc, x| func(x, acc))
}
#[document_signature]
#[document_type_parameters(
"The lifetime of the elements.",
"The brand of the cloneable function to use.",
"The type of the elements in the vector.",
"The type of the accumulator."
)]
#[document_parameters(
"The function to apply to the accumulator and each element.",
"The initial value of the accumulator.",
"The vector to fold."
)]
#[document_returns("The final accumulator value.")]
#[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: CloneableFn + 'a, {
fa.into_iter().fold(initial, func)
}
#[document_signature]
#[document_type_parameters(
"The lifetime of the elements.",
"The brand of the cloneable function to use.",
"The type of the elements in the vector.",
"The type of the monoid."
)]
#[document_parameters("The mapping function.", "The vector to fold.")]
#[document_returns("The combined monoid value.")]
#[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: CloneableFn + 'a, {
fa.into_iter().map(func).fold(M::empty(), |acc, x| M::append(acc, x))
}
}
impl Traversable for VecBrand {
#[document_signature]
#[document_type_parameters(
"The lifetime of the elements.",
"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 vector to traverse."
)]
#[document_returns("The vector 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,
Apply!(<F as Kind!( type Of<'a, T: 'a>: 'a; )>::Of<'a, B>): Clone, {
let len = ta.len();
ta.into_iter().fold(F::pure(Vec::with_capacity(len)), |acc, x| {
F::lift2(
|mut v, b| {
v.push(b);
v
},
acc,
func(x),
)
})
}
#[document_signature]
#[document_type_parameters(
"The lifetime of the elements.",
"The type of the elements in the traversable structure.",
"The applicative context."
)]
#[document_parameters("The vector containing the applicative values.")]
#[document_returns("The vector wrapped in the applicative context.")]
#[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, {
let len = ta.len();
ta.into_iter().fold(F::pure(Vec::with_capacity(len)), |acc, x| {
F::lift2(
|mut v, a| {
v.push(a);
v
},
acc,
x,
)
})
}
}
impl WithIndex for VecBrand {
type Index = usize;
}
impl FunctorWithIndex for VecBrand {
#[document_signature]
#[document_type_parameters(
"The lifetime of the elements.",
"The type of the elements in the vector.",
"The type of the elements in the resulting vector."
)]
#[document_parameters(
"The function to apply to each element and its index.",
"The vector to map over."
)]
#[document_returns("A new vector containing the results of applying the function.")]
#[document_examples]
fn map_with_index<'a, A: 'a, B: 'a>(
f: impl Fn(usize, A) -> B + 'a,
fa: Vec<A>,
) -> Vec<B> {
fa.into_iter().enumerate().map(|(i, a)| f(i, a)).collect()
}
}
impl FoldableWithIndex for VecBrand {
#[document_signature]
#[document_type_parameters(
"The lifetime of the elements.",
"The type of the elements in the vector.",
"The monoid type."
)]
#[document_parameters(
"The function to apply to each element and its index.",
"The vector to fold."
)]
#[document_returns("The combined monoid value.")]
#[document_examples]
fn fold_map_with_index<'a, A: 'a + Clone, R: Monoid>(
f: impl Fn(usize, A) -> R + 'a,
fa: Vec<A>,
) -> R {
fa.into_iter()
.enumerate()
.map(|(i, a)| f(i, a))
.fold(R::empty(), |acc, x| R::append(acc, x))
}
}
impl TraversableWithIndex for VecBrand {
#[document_signature]
#[document_type_parameters(
"The lifetime of the elements.",
"The type of the elements in the vector.",
"The type of the elements in the resulting vector.",
"The applicative context."
)]
#[document_parameters(
"The function to apply to each element and its index, returning a value in an applicative context.",
"The vector to traverse."
)]
#[document_returns("The vector wrapped in the applicative context.")]
#[document_examples]
fn traverse_with_index<'a, A: 'a, B: 'a + Clone, M: Applicative>(
f: impl Fn(usize, A) -> M::Of<'a, B> + 'a,
ta: Vec<A>,
) -> M::Of<'a, Vec<B>> {
let len = ta.len();
ta.into_iter().enumerate().fold(M::pure(Vec::with_capacity(len)), |acc, (i, x)| {
M::lift2(
|mut v, b| {
v.push(b);
v
},
acc,
f(i, x),
)
})
}
}
#[document_type_parameters("The type of the elements in the vector.")]
impl<A: Clone> Semigroup for Vec<A> {
#[document_signature]
#[document_parameters("The first vector.", "The second vector.")]
#[document_returns("The concatenated vector.")]
#[document_examples]
fn append(
a: Self,
b: Self,
) -> Self {
[a, b].concat()
}
}
#[document_type_parameters("The type of the elements in the vector.")]
impl<A: Clone> Monoid for Vec<A> {
#[document_signature]
#[document_returns("An empty vector.")]
#[document_examples]
fn empty() -> Self {
Vec::new()
}
}
impl VecBrand {
#[document_signature]
#[document_type_parameters(
"The lifetime of the elements.",
"The input element type.",
"The output element type."
)]
#[document_parameters(
"The function to apply to each element. Must be `Send + Sync`.",
"The vector to map over."
)]
#[document_returns("A new vector containing the mapped elements.")]
#[document_examples]
pub fn par_map<'a, A: 'a + Send, B: 'a + Send>(
f: impl Fn(A) -> B + Send + Sync + 'a,
fa: Vec<A>,
) -> Vec<B> {
#[cfg(feature = "rayon")]
{
use rayon::prelude::*;
fa.into_par_iter().map(f).collect()
}
#[cfg(not(feature = "rayon"))]
fa.into_iter().map(f).collect()
}
#[document_signature]
#[document_type_parameters("The lifetime of the elements.", "The element type.")]
#[document_parameters("The vector of options.")]
#[document_returns("A new vector containing the unwrapped `Some` values.")]
#[document_examples]
pub fn par_compact<'a, A: 'a + Send>(fa: Vec<Option<A>>) -> Vec<A> {
#[cfg(feature = "rayon")]
{
use rayon::prelude::*;
fa.into_par_iter().flatten().collect()
}
#[cfg(not(feature = "rayon"))]
fa.into_iter().flatten().collect()
}
#[document_signature]
#[document_type_parameters(
"The lifetime of the elements.",
"The error type.",
"The success type."
)]
#[document_parameters("The vector of results.")]
#[document_returns(
"A pair `(errs, oks)` where `errs` contains the `Err` values and `oks` the `Ok` values."
)]
#[document_examples]
pub fn par_separate<'a, E: 'a + Send, O: 'a + Send>(
fa: Vec<Result<O, E>>
) -> (Vec<E>, Vec<O>) {
#[cfg(feature = "rayon")]
{
use rayon::{
iter::Either,
prelude::*,
};
fa.into_par_iter().partition_map(|r| match r {
Ok(o) => Either::Right(o),
Err(e) => Either::Left(e),
})
}
#[cfg(not(feature = "rayon"))]
{
let mut errs = Vec::new();
let mut oks = Vec::new();
for result in fa {
match result {
Ok(o) => oks.push(o),
Err(e) => errs.push(e),
}
}
(errs, oks)
}
}
#[document_signature]
#[document_type_parameters(
"The lifetime of the elements.",
"The input element type.",
"The output element type."
)]
#[document_parameters(
"The function to apply. Must be `Send + Sync`.",
"The vector to filter and map."
)]
#[document_returns("A new vector containing the `Some` results of applying `f`.")]
#[document_examples]
pub fn par_filter_map<'a, A: 'a + Send, B: 'a + Send>(
f: impl Fn(A) -> Option<B> + Send + Sync + 'a,
fa: Vec<A>,
) -> Vec<B> {
#[cfg(feature = "rayon")]
{
use rayon::prelude::*;
fa.into_par_iter().filter_map(f).collect()
}
#[cfg(not(feature = "rayon"))]
fa.into_iter().filter_map(f).collect()
}
#[document_signature]
#[document_type_parameters("The lifetime of the elements.", "The element type.")]
#[document_parameters("The predicate. Must be `Send + Sync`.", "The vector to filter.")]
#[document_returns("A new vector containing only the elements satisfying `f`.")]
#[document_examples]
pub fn par_filter<'a, A: 'a + Send>(
f: impl Fn(&A) -> bool + Send + Sync + 'a,
fa: Vec<A>,
) -> Vec<A> {
#[cfg(feature = "rayon")]
{
use rayon::prelude::*;
fa.into_par_iter().filter(|a| f(a)).collect()
}
#[cfg(not(feature = "rayon"))]
fa.into_iter().filter(|a| f(a)).collect()
}
#[document_signature]
#[document_type_parameters(
"The lifetime of the elements.",
"The element type.",
"The monoid type."
)]
#[document_parameters(
"The function mapping each element to a monoid value. Must be `Send + Sync`.",
"The vector to fold."
)]
#[document_returns("The combined monoid value.")]
#[document_examples]
pub fn par_fold_map<'a, A: 'a + Send, M: Monoid + Send + 'a>(
f: impl Fn(A) -> M + Send + Sync + 'a,
fa: Vec<A>,
) -> M {
#[cfg(feature = "rayon")]
{
use rayon::prelude::*;
fa.into_par_iter().map(f).reduce(M::empty, |acc, m| M::append(acc, m))
}
#[cfg(not(feature = "rayon"))]
fa.into_iter().map(f).fold(M::empty(), |acc, m| M::append(acc, m))
}
#[document_signature]
#[document_type_parameters(
"The lifetime of the elements.",
"The input element type.",
"The output element type."
)]
#[document_parameters(
"The function to apply to each index and element. Must be `Send + Sync`.",
"The vector to map over."
)]
#[document_returns("A new vector containing the mapped elements.")]
#[document_examples]
pub fn par_map_with_index<'a, A: 'a + Send, B: 'a + Send>(
f: impl Fn(usize, A) -> B + Send + Sync + 'a,
fa: Vec<A>,
) -> Vec<B> {
#[cfg(feature = "rayon")]
{
use rayon::prelude::*;
fa.into_par_iter().enumerate().map(|(i, a)| f(i, a)).collect()
}
#[cfg(not(feature = "rayon"))]
fa.into_iter().enumerate().map(|(i, a)| f(i, a)).collect()
}
#[document_signature]
#[document_type_parameters(
"The lifetime of the elements.",
"The element type.",
"The monoid type."
)]
#[document_parameters(
"The function mapping each index and element to a monoid value. Must be `Send + Sync`.",
"The vector to fold."
)]
#[document_returns("The combined monoid value.")]
#[document_examples]
pub fn par_fold_map_with_index<'a, A: 'a + Send, M: Monoid + Send + 'a>(
f: impl Fn(usize, A) -> M + Send + Sync + 'a,
fa: Vec<A>,
) -> M {
#[cfg(feature = "rayon")]
{
use rayon::prelude::*;
fa.into_par_iter()
.enumerate()
.map(|(i, a)| f(i, a))
.reduce(M::empty, |acc, m| M::append(acc, m))
}
#[cfg(not(feature = "rayon"))]
fa.into_iter()
.enumerate()
.map(|(i, a)| f(i, a))
.fold(M::empty(), |acc, m| M::append(acc, m))
}
}
impl ParFunctor for VecBrand {
#[document_signature]
#[document_type_parameters(
"The lifetime of the elements.",
"The input element type.",
"The output element type."
)]
#[document_parameters(
"The function to apply to each element. Must be `Send + Sync`.",
"The vector to map over."
)]
#[document_returns("A new vector containing the mapped elements.")]
#[document_examples]
fn par_map<'a, A: 'a + Send, B: 'a + Send>(
f: impl Fn(A) -> B + Send + Sync + '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>) {
VecBrand::par_map(f, fa)
}
}
impl ParCompactable for VecBrand {
#[document_signature]
#[document_type_parameters("The lifetime of the elements.", "The element type.")]
#[document_parameters("The vector of options.")]
#[document_returns("A new vector containing the unwrapped `Some` values.")]
#[document_examples]
fn par_compact<'a, A: 'a + Send>(
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>) {
VecBrand::par_compact(fa)
}
#[document_signature]
#[document_type_parameters(
"The lifetime of the elements.",
"The error type.",
"The success type."
)]
#[document_parameters("The vector of results.")]
#[document_returns(
"A pair `(errs, oks)` where `errs` contains the `Err` values and `oks` the `Ok` values."
)]
#[document_examples]
fn par_separate<'a, E: 'a + Send, O: 'a + Send>(
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>),
) {
VecBrand::par_separate(fa)
}
}
impl ParFilterable for VecBrand {
#[document_signature]
#[document_type_parameters(
"The lifetime of the elements.",
"The input element type.",
"The output element type."
)]
#[document_parameters(
"The function to apply. Must be `Send + Sync`.",
"The vector to filter and map."
)]
#[document_returns("A new vector containing the `Some` results of applying `f`.")]
#[document_examples]
fn par_filter_map<'a, A: 'a + Send, B: 'a + Send>(
f: impl Fn(A) -> Option<B> + Send + Sync + '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>) {
VecBrand::par_filter_map(f, fa)
}
#[document_signature]
#[document_type_parameters("The lifetime of the elements.", "The element type.")]
#[document_parameters("The predicate. Must be `Send + Sync`.", "The vector to filter.")]
#[document_returns("A new vector containing only the elements satisfying `f`.")]
#[document_examples]
fn par_filter<'a, A: 'a + Send>(
f: impl Fn(&A) -> bool + Send + Sync + '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>) {
VecBrand::par_filter(f, fa)
}
}
impl ParFoldable for VecBrand {
#[document_signature]
#[document_type_parameters(
"The lifetime of the elements.",
"The element type.",
"The monoid type."
)]
#[document_parameters(
"The function mapping each element to a monoid value. Must be `Send + Sync`.",
"The vector to fold."
)]
#[document_returns("The combined monoid value.")]
#[document_examples]
fn par_fold_map<'a, A: 'a + Send, M: Monoid + Send + 'a>(
f: impl Fn(A) -> M + Send + Sync + 'a,
fa: Apply!(<Self as Kind!( type Of<'a, T: 'a>: 'a; )>::Of<'a, A>),
) -> M {
VecBrand::par_fold_map(f, fa)
}
}
impl ParFunctorWithIndex for VecBrand {
#[document_signature]
#[document_type_parameters(
"The lifetime of the elements.",
"The input element type.",
"The output element type."
)]
#[document_parameters(
"The function to apply to each index and element. Must be `Send + Sync`.",
"The vector to map over."
)]
#[document_returns("A new vector containing the mapped elements.")]
#[document_examples]
fn par_map_with_index<'a, A: 'a + Send, B: 'a + Send>(
f: impl Fn(usize, A) -> B + Send + Sync + '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>)
where
usize: Send + Sync + Copy + 'a, {
VecBrand::par_map_with_index(f, fa)
}
}
impl ParFoldableWithIndex for VecBrand {
#[document_signature]
#[document_type_parameters(
"The lifetime of the elements.",
"The element type.",
"The monoid type."
)]
#[document_parameters(
"The function mapping each index and element to a monoid value. Must be `Send + Sync`.",
"The vector to fold."
)]
#[document_returns("The combined monoid value.")]
#[document_examples]
fn par_fold_map_with_index<'a, A: 'a + Send, M: Monoid + Send + 'a>(
f: impl Fn(usize, A) -> M + Send + Sync + 'a,
fa: Apply!(<Self as Kind!( type Of<'a, T: 'a>: 'a; )>::Of<'a, A>),
) -> M
where
usize: Send + Sync + Copy + 'a, {
VecBrand::par_fold_map_with_index(f, fa)
}
}
impl Compactable for VecBrand {
#[document_signature]
#[document_type_parameters("The lifetime of the elements.", "The type of the elements.")]
#[document_parameters("The vector of options.")]
#[document_returns("The flattened vector.")]
#[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.into_iter().flatten().collect()
}
#[document_signature]
#[document_type_parameters(
"The lifetime of the elements.",
"The type of the error value.",
"The type of the success value."
)]
#[document_parameters("The vector of results.")]
#[document_returns("A pair of vectors.")]
#[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>),
) {
let mut oks = Vec::new();
let mut errs = Vec::new();
for result in fa {
match result {
Ok(o) => oks.push(o),
Err(e) => errs.push(e),
}
}
(errs, oks)
}
}
impl Filterable for VecBrand {
#[document_signature]
#[document_type_parameters(
"The lifetime of the elements.",
"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 vector to partition.")]
#[document_returns("A pair of vectors.")]
#[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>),
) {
let mut oks = Vec::new();
let mut errs = Vec::new();
for a in fa {
match func(a) {
Ok(o) => oks.push(o),
Err(e) => errs.push(e),
}
}
(errs, oks)
}
#[document_signature]
#[document_type_parameters("The lifetime of the elements.", "The type of the elements.")]
#[document_parameters("The predicate.", "The vector to partition.")]
#[document_returns("A pair of vectors.")]
#[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>),
) {
let (satisfied, not_satisfied): (Vec<A>, Vec<A>) =
fa.into_iter().partition(|a| func(a.clone()));
(not_satisfied, satisfied)
}
#[document_signature]
#[document_type_parameters(
"The lifetime of the elements.",
"The type of the input value.",
"The type of the result of applying the function."
)]
#[document_parameters("The function to apply.", "The vector to filter and map.")]
#[document_returns("The filtered and mapped vector.")]
#[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.into_iter().filter_map(func).collect()
}
#[document_signature]
#[document_type_parameters("The lifetime of the elements.", "The type of the elements.")]
#[document_parameters("The predicate.", "The vector to filter.")]
#[document_returns("The filtered vector.")]
#[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.into_iter().filter(|a| func(a.clone())).collect()
}
}
impl Witherable for VecBrand {
#[document_signature]
#[document_type_parameters(
"The lifetime of the elements.",
"The applicative context.",
"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 vector to partition.")]
#[document_returns("The partitioned vector 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, {
ta.into_iter().fold(M::pure((Vec::new(), Vec::new())), |acc, x| {
M::lift2(
|mut pair, res| {
match res {
Ok(o) => pair.1.push(o),
Err(e) => pair.0.push(e),
}
pair
},
acc,
func(x),
)
})
}
#[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 vector to filter and map."
)]
#[document_returns("The filtered and mapped vector 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, {
ta.into_iter().fold(M::pure(Vec::new()), |acc, x| {
M::lift2(
|mut v, opt_b| {
if let Some(b) = opt_b {
v.push(b);
}
v
},
acc,
func(x),
)
})
}
}
impl Extend for VecBrand {
#[document_signature]
#[document_type_parameters(
"The lifetime of the values.",
"The type of the elements in the vector.",
"The result type of the extension function."
)]
#[document_parameters(
"The function that consumes a suffix vector and produces a value.",
"The vector to extend over."
)]
#[document_returns(
"A new vector containing the results of applying the function to each suffix."
)]
#[document_examples]
fn extend<'a, A: 'a + Clone, B: 'a>(
f: impl Fn(Apply!(<Self as Kind!( type Of<'a, T: 'a>: 'a; )>::Of<'a, A>)) -> B + 'a,
wa: 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>) {
(0 .. wa.len()).map(|i| f(wa.get(i ..).unwrap_or_default().to_vec())).collect()
}
}
impl MonadRec for VecBrand {
#[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("A vector of all completed results.")]
#[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 done: Vec<B> = Vec::new();
let mut pending: Vec<A> = vec![initial];
while !pending.is_empty() {
let mut next_pending: Vec<A> = Vec::new();
for a in pending {
for step in func(a) {
match step {
ControlFlow::Continue(next) => next_pending.push(next),
ControlFlow::Break(b) => done.push(b),
}
}
}
pending = next_pending;
}
done
}
}
}
#[cfg(test)]
mod tests {
use {
crate::{
brands::*,
classes::CloneableFn,
functions::*,
},
quickcheck_macros::quickcheck,
};
#[quickcheck]
fn functor_identity(x: Vec<i32>) -> bool {
map::<VecBrand, _, _>(identity, x.clone()) == x
}
#[quickcheck]
fn functor_composition(x: Vec<i32>) -> bool {
let f = |x: i32| x.wrapping_add(1);
let g = |x: i32| x.wrapping_mul(2);
map::<VecBrand, _, _>(compose(f, g), x.clone())
== map::<VecBrand, _, _>(f, map::<VecBrand, _, _>(g, x))
}
#[quickcheck]
fn applicative_identity(v: Vec<i32>) -> bool {
apply::<RcFnBrand, VecBrand, _, _>(
pure::<VecBrand, _>(<RcFnBrand as CloneableFn>::new(identity)),
v.clone(),
) == v
}
#[quickcheck]
fn applicative_homomorphism(x: i32) -> bool {
let f = |x: i32| x.wrapping_mul(2);
apply::<RcFnBrand, VecBrand, _, _>(
pure::<VecBrand, _>(<RcFnBrand as CloneableFn>::new(f)),
pure::<VecBrand, _>(x),
) == pure::<VecBrand, _>(f(x))
}
#[quickcheck]
fn applicative_composition(
w: Vec<i32>,
u_seeds: Vec<i32>,
v_seeds: Vec<i32>,
) -> bool {
let u_fns: Vec<_> = u_seeds
.iter()
.map(|&i| <RcFnBrand as CloneableFn>::new(move |x: i32| x.wrapping_add(i)))
.collect();
let v_fns: Vec<_> = v_seeds
.iter()
.map(|&i| <RcFnBrand as CloneableFn>::new(move |x: i32| x.wrapping_mul(i)))
.collect();
let vw = apply::<RcFnBrand, VecBrand, _, _>(v_fns.clone(), w.clone());
let rhs = apply::<RcFnBrand, VecBrand, _, _>(u_fns.clone(), vw);
let uv_fns: Vec<_> = u_fns
.iter()
.flat_map(|uf| {
v_fns.iter().map(move |vf| {
let uf = uf.clone();
let vf = vf.clone();
<RcFnBrand as CloneableFn>::new(move |x| uf(vf(x)))
})
})
.collect();
let lhs = apply::<RcFnBrand, VecBrand, _, _>(uv_fns, w);
lhs == rhs
}
#[quickcheck]
fn applicative_interchange(y: i32) -> bool {
let f = |x: i32| x.wrapping_mul(2);
let u = vec![<RcFnBrand as CloneableFn>::new(f)];
let lhs = apply::<RcFnBrand, VecBrand, _, _>(u.clone(), pure::<VecBrand, _>(y));
let rhs_fn =
<RcFnBrand as CloneableFn>::new(move |f: std::rc::Rc<dyn Fn(i32) -> i32>| f(y));
let rhs = apply::<RcFnBrand, VecBrand, _, _>(pure::<VecBrand, _>(rhs_fn), u);
lhs == rhs
}
#[quickcheck]
fn semigroup_associativity(
a: Vec<i32>,
b: Vec<i32>,
c: Vec<i32>,
) -> bool {
append(a.clone(), append(b.clone(), c.clone())) == append(append(a, b), c)
}
#[quickcheck]
fn monoid_left_identity(a: Vec<i32>) -> bool {
append(empty::<Vec<i32>>(), a.clone()) == a
}
#[quickcheck]
fn monoid_right_identity(a: Vec<i32>) -> bool {
append(a.clone(), empty::<Vec<i32>>()) == a
}
#[quickcheck]
fn monad_left_identity(a: i32) -> bool {
let f = |x: i32| vec![x.wrapping_mul(2)];
bind::<VecBrand, _, _>(pure::<VecBrand, _>(a), f) == f(a)
}
#[quickcheck]
fn monad_right_identity(m: Vec<i32>) -> bool {
bind::<VecBrand, _, _>(m.clone(), pure::<VecBrand, _>) == m
}
#[quickcheck]
fn monad_associativity(m: Vec<i32>) -> bool {
let f = |x: i32| vec![x.wrapping_mul(2)];
let g = |x: i32| vec![x.wrapping_add(1)];
bind::<VecBrand, _, _>(bind::<VecBrand, _, _>(m.clone(), f), g)
== bind::<VecBrand, _, _>(m, |x| bind::<VecBrand, _, _>(f(x), g))
}
#[test]
fn map_empty() {
assert_eq!(map::<VecBrand, _, _>(|x: i32| x + 1, vec![] as Vec<i32>), vec![] as Vec<i32>);
}
#[test]
fn bind_empty() {
assert_eq!(
bind::<VecBrand, _, _>(vec![] as Vec<i32>, |x: i32| vec![x + 1]),
vec![] as Vec<i32>
);
}
#[test]
fn bind_returning_empty() {
assert_eq!(
bind::<VecBrand, _, _>(vec![1, 2, 3], |_| vec![] as Vec<i32>),
vec![] as Vec<i32>
);
}
#[test]
fn fold_right_empty() {
assert_eq!(
crate::classes::foldable::fold_right::<RcFnBrand, VecBrand, _, _>(
|x: i32, acc| x + acc,
0,
vec![]
),
0
);
}
#[test]
fn fold_left_empty() {
assert_eq!(
crate::classes::foldable::fold_left::<RcFnBrand, VecBrand, _, _>(
|acc, x: i32| acc + x,
0,
vec![]
),
0
);
}
#[test]
fn traverse_empty() {
use crate::brands::OptionBrand;
assert_eq!(
crate::classes::traversable::traverse::<VecBrand, _, _, OptionBrand>(
|x: i32| Some(x + 1),
vec![]
),
Some(vec![])
);
}
#[test]
fn traverse_returning_empty() {
use crate::brands::OptionBrand;
assert_eq!(
crate::classes::traversable::traverse::<VecBrand, _, _, OptionBrand>(
|_: i32| None::<i32>,
vec![1, 2, 3]
),
None
);
}
#[test]
fn construct_empty_tail() {
assert_eq!(VecBrand::construct(1, vec![]), vec![1]);
}
#[test]
fn deconstruct_empty() {
assert_eq!(VecBrand::deconstruct::<i32>(&[]), None);
}
#[test]
fn par_map_basic() {
let v = vec![1, 2, 3];
let result: Vec<i32> = par_map::<VecBrand, _, _>(|x: i32| x * 2, v);
assert_eq!(result, vec![2, 4, 6]);
}
#[test]
fn par_filter_basic() {
let v = vec![1, 2, 3, 4, 5];
let result: Vec<i32> = par_filter::<VecBrand, _>(|x: &i32| x % 2 == 0, v);
assert_eq!(result, vec![2, 4]);
}
#[test]
fn par_filter_map_basic() {
let v = vec![1, 2, 3, 4, 5];
let result: Vec<i32> = par_filter_map::<VecBrand, _, _>(
|x: i32| if x % 2 == 0 { Some(x * 10) } else { None },
v,
);
assert_eq!(result, vec![20, 40]);
}
#[test]
fn par_compact_basic() {
let v = vec![Some(1), None, Some(3), None, Some(5)];
let result: Vec<i32> = par_compact::<VecBrand, _>(v);
assert_eq!(result, vec![1, 3, 5]);
}
#[test]
fn par_separate_basic() {
let v: Vec<Result<i32, &str>> = vec![Ok(1), Err("a"), Ok(3), Err("b")];
let (errs, oks): (Vec<&str>, Vec<i32>) = par_separate::<VecBrand, _, _>(v);
assert_eq!(errs, vec!["a", "b"]);
assert_eq!(oks, vec![1, 3]);
}
#[test]
fn par_map_with_index_basic() {
let v = vec![10, 20, 30];
let result: Vec<i32> = par_map_with_index::<VecBrand, _, _>(|i, x: i32| x + i as i32, v);
assert_eq!(result, vec![10, 21, 32]);
}
#[test]
fn par_fold_map_empty() {
let v: Vec<i32> = vec![];
assert_eq!(par_fold_map::<VecBrand, _, _>(|x: i32| x.to_string(), v), "".to_string());
}
#[test]
fn par_fold_map_multiple() {
let v = vec![1, 2, 3];
assert_eq!(par_fold_map::<VecBrand, _, _>(|x: i32| x.to_string(), v), "123".to_string());
}
#[test]
fn par_fold_map_with_index_basic() {
let v = vec![10, 20, 30];
let result: String =
par_fold_map_with_index::<VecBrand, _, _>(|i, x: i32| format!("{i}:{x}"), v);
assert_eq!(result, "0:101:202:30");
}
#[quickcheck]
fn filterable_filter_map_identity(x: Vec<Option<i32>>) -> bool {
filter_map::<VecBrand, _, _>(identity, x.clone()) == compact::<VecBrand, _>(x)
}
#[quickcheck]
fn filterable_filter_map_just(x: Vec<i32>) -> bool {
filter_map::<VecBrand, _, _>(Some, x.clone()) == x
}
#[quickcheck]
fn filterable_filter_map_composition(x: Vec<i32>) -> bool {
let r = |i: i32| if i % 2 == 0 { Some(i) } else { None };
let l = |i: i32| if i > 5 { Some(i) } else { None };
let composed = |i| bind::<OptionBrand, _, _>(r(i), l);
filter_map::<VecBrand, _, _>(composed, x.clone())
== filter_map::<VecBrand, _, _>(l, filter_map::<VecBrand, _, _>(r, x))
}
#[quickcheck]
fn filterable_filter_consistency(x: Vec<i32>) -> bool {
let p = |i: i32| i % 2 == 0;
let maybe_bool = |i| if p(i) { Some(i) } else { None };
filter::<VecBrand, _>(p, x.clone()) == filter_map::<VecBrand, _, _>(maybe_bool, x)
}
#[quickcheck]
fn filterable_partition_map_identity(x: Vec<Result<i32, i32>>) -> bool {
partition_map::<VecBrand, _, _, _>(identity, x.clone()) == separate::<VecBrand, _, _>(x)
}
#[quickcheck]
fn filterable_partition_map_right_identity(x: Vec<i32>) -> bool {
let (_, oks) = partition_map::<VecBrand, _, _, _>(Ok::<_, i32>, x.clone());
oks == x
}
#[quickcheck]
fn filterable_partition_map_left_identity(x: Vec<i32>) -> bool {
let (errs, _) = partition_map::<VecBrand, _, _, _>(Err::<i32, _>, x.clone());
errs == x
}
#[quickcheck]
fn filterable_partition_consistency(x: Vec<i32>) -> bool {
let p = |i: i32| i % 2 == 0;
let either_bool = |i| if p(i) { Ok(i) } else { Err(i) };
let (not_satisfied, satisfied) = partition::<VecBrand, _>(p, x.clone());
let (errs, oks) = partition_map::<VecBrand, _, _, _>(either_bool, x);
satisfied == oks && not_satisfied == errs
}
#[quickcheck]
fn witherable_identity(x: Vec<i32>) -> bool {
wither::<VecBrand, OptionBrand, _, _>(|i| Some(Some(i)), x.clone()) == Some(x)
}
#[quickcheck]
fn witherable_wilt_consistency(x: Vec<i32>) -> bool {
let p = |i: i32| Some(if i % 2 == 0 { Ok(i) } else { Err(i) });
let lhs = wilt::<VecBrand, OptionBrand, _, _, _>(p, x.clone());
let rhs = crate::classes::functor::map::<OptionBrand, _, _>(
separate::<VecBrand, _, _>,
traverse::<VecBrand, _, _, OptionBrand>(p, x),
);
lhs == rhs
}
#[quickcheck]
fn witherable_wither_consistency(x: Vec<i32>) -> bool {
let p = |i: i32| Some(if i % 2 == 0 { Some(i) } else { None });
let lhs = wither::<VecBrand, OptionBrand, _, _>(p, x.clone());
let rhs = crate::classes::functor::map::<OptionBrand, _, _>(
compact::<VecBrand, _>,
traverse::<VecBrand, _, _, OptionBrand>(p, x),
);
lhs == rhs
}
#[quickcheck]
fn alt_associativity(
x: Vec<i32>,
y: Vec<i32>,
z: Vec<i32>,
) -> bool {
alt::<VecBrand, _>(alt::<VecBrand, _>(x.clone(), y.clone()), z.clone())
== alt::<VecBrand, _>(x, alt::<VecBrand, _>(y, z))
}
#[quickcheck]
fn alt_distributivity(
x: Vec<i32>,
y: Vec<i32>,
) -> bool {
let f = |i: i32| i.wrapping_mul(2).wrapping_add(1);
map::<VecBrand, _, _>(f, alt::<VecBrand, _>(x.clone(), y.clone()))
== alt::<VecBrand, _>(map::<VecBrand, _, _>(f, x), map::<VecBrand, _, _>(f, y))
}
#[quickcheck]
fn plus_left_identity(x: Vec<i32>) -> bool {
alt::<VecBrand, _>(plus_empty::<VecBrand, i32>(), x.clone()) == x
}
#[quickcheck]
fn plus_right_identity(x: Vec<i32>) -> bool {
alt::<VecBrand, _>(x.clone(), plus_empty::<VecBrand, i32>()) == x
}
#[test]
fn plus_annihilation() {
let f = |i: i32| i.wrapping_mul(2);
assert_eq!(
map::<VecBrand, _, _>(f, plus_empty::<VecBrand, i32>()),
plus_empty::<VecBrand, i32>(),
);
}
#[quickcheck]
fn compactable_functor_identity(fa: Vec<i32>) -> bool {
compact::<VecBrand, _>(map::<VecBrand, _, _>(Some, fa.clone())) == fa
}
#[test]
fn compactable_plus_annihilation_empty() {
assert_eq!(
compact::<VecBrand, _>(plus_empty::<VecBrand, Option<i32>>()),
plus_empty::<VecBrand, i32>(),
);
}
#[quickcheck]
fn compactable_plus_annihilation_map(xs: Vec<i32>) -> bool {
compact::<VecBrand, _>(map::<VecBrand, _, _>(|_: i32| None::<i32>, xs))
== plus_empty::<VecBrand, i32>()
}
#[test]
fn compact_empty() {
assert_eq!(compact::<VecBrand, i32>(vec![] as Vec<Option<i32>>), vec![] as Vec<i32>);
}
#[test]
fn compact_with_none() {
assert_eq!(compact::<VecBrand, i32>(vec![Some(1), None, Some(2)]), vec![1, 2]);
}
#[test]
fn separate_empty() {
let (errs, oks) = separate::<VecBrand, i32, i32>(vec![] as Vec<Result<i32, i32>>);
assert_eq!(oks, vec![] as Vec<i32>);
assert_eq!(errs, vec![] as Vec<i32>);
}
#[test]
fn separate_mixed() {
let (errs, oks) = separate::<VecBrand, i32, i32>(vec![Ok(1), Err(2), Ok(3)]);
assert_eq!(oks, vec![1, 3]);
assert_eq!(errs, vec![2]);
}
#[test]
fn partition_map_empty() {
let (errs, oks) =
partition_map::<VecBrand, i32, i32, _>(|x: i32| Ok::<i32, i32>(x), vec![]);
assert_eq!(oks, vec![] as Vec<i32>);
assert_eq!(errs, vec![] as Vec<i32>);
}
#[test]
fn partition_empty() {
let (not_satisfied, satisfied) = partition::<VecBrand, i32>(|x: i32| x > 0, vec![]);
assert_eq!(satisfied, vec![] as Vec<i32>);
assert_eq!(not_satisfied, vec![] as Vec<i32>);
}
#[test]
fn filter_map_empty() {
assert_eq!(filter_map::<VecBrand, i32, _>(|x: i32| Some(x), vec![]), vec![] as Vec<i32>);
}
#[test]
fn filter_empty() {
assert_eq!(filter::<VecBrand, i32>(|x: i32| x > 0, vec![]), vec![] as Vec<i32>);
}
#[test]
fn wilt_empty() {
let res = wilt::<VecBrand, OptionBrand, _, _, _>(|x: i32| Some(Ok::<i32, i32>(x)), vec![]);
assert_eq!(res, Some((vec![], vec![])));
}
#[test]
fn wither_empty() {
let res = wither::<VecBrand, OptionBrand, _, _>(|x: i32| Some(Some(x)), vec![]);
assert_eq!(res, Some(vec![]));
}
#[test]
fn test_large_vector_par_fold_map() {
use crate::types::Additive;
let xs: Vec<i32> = (0 .. 100000).collect();
let res = par_fold_map::<VecBrand, _, _>(|x: i32| Additive(x as i64), xs);
assert_eq!(res, Additive(4999950000));
}
#[quickcheck]
fn prop_par_map_equals_map(xs: Vec<i32>) -> bool {
let f = |x: i32| x.wrapping_add(1);
let seq_res = map::<VecBrand, _, _>(f, xs.clone());
let par_res = par_map::<VecBrand, _, _>(f, xs);
seq_res == par_res
}
#[quickcheck]
fn prop_par_fold_map_equals_fold_map(xs: Vec<i32>) -> bool {
use crate::types::Additive;
let f = |x: i32| Additive(x as i64);
let seq_res = crate::classes::foldable::fold_map::<crate::brands::RcFnBrand, VecBrand, _, _>(
f,
xs.clone(),
);
let par_res = par_fold_map::<VecBrand, _, _>(f, xs);
seq_res == par_res
}
#[quickcheck]
fn prop_par_fold_map_empty_is_empty(xs: Vec<i32>) -> bool {
use crate::types::Additive;
if !xs.is_empty() {
return true;
}
let par_res = par_fold_map::<VecBrand, _, _>(|x: i32| Additive(x as i64), xs);
par_res == empty::<Additive<i64>>()
}
#[quickcheck]
fn monad_rec_identity(x: i32) -> bool {
use {
crate::classes::monad_rec::tail_rec_m,
core::ops::ControlFlow,
};
tail_rec_m::<VecBrand, _, _>(|a| vec![ControlFlow::Break(a)], x) == vec![x]
}
#[test]
fn monad_rec_linear() {
use {
crate::classes::monad_rec::tail_rec_m,
core::ops::ControlFlow,
};
let result = tail_rec_m::<VecBrand, _, _>(
|n| {
if n < 5 { vec![ControlFlow::Continue(n + 1)] } else { vec![ControlFlow::Break(n)] }
},
0,
);
assert_eq!(result, vec![5]);
}
#[test]
fn monad_rec_branching() {
use {
crate::classes::monad_rec::tail_rec_m,
core::ops::ControlFlow,
};
let result = tail_rec_m::<VecBrand, _, _>(
|n: i32| {
if n < 2 {
vec![ControlFlow::Continue(n + 1), ControlFlow::Break(n * 100)]
} else {
vec![ControlFlow::Break(n * 100)]
}
},
0,
);
assert_eq!(result, vec![0, 100, 200]);
}
#[test]
fn monad_rec_empty() {
use {
crate::classes::monad_rec::tail_rec_m,
core::ops::ControlFlow,
};
let result: Vec<i32> =
tail_rec_m::<VecBrand, _, _>(|_n| Vec::<ControlFlow<i32, i32>>::new(), 0);
assert_eq!(result, Vec::<i32>::new());
}
#[test]
fn extend_sum_of_suffixes() {
use crate::classes::extend::extend;
let result = extend::<VecBrand, _, _>(|v: Vec<i32>| v.iter().sum::<i32>(), vec![1, 2, 3]);
assert_eq!(result, vec![6, 5, 3]);
}
#[quickcheck]
fn extend_associativity(w: Vec<i32>) -> bool {
use crate::classes::extend::extend;
let g = |v: Vec<i32>| v.iter().fold(0i32, |a, b| a.wrapping_mul(2).wrapping_add(*b));
let f = |v: Vec<i32>| v.iter().fold(0i32, |a, b| a.wrapping_add(b.wrapping_add(1)));
let lhs = extend::<VecBrand, _, _>(f, extend::<VecBrand, _, _>(g, w.clone()));
let rhs = extend::<VecBrand, _, _>(|w: Vec<i32>| f(extend::<VecBrand, _, _>(g, w)), w);
lhs == rhs
}
#[test]
fn extend_duplicate_suffixes() {
use crate::classes::extend::duplicate;
let result = duplicate::<VecBrand, _>(vec![1, 2, 3]);
assert_eq!(result, vec![vec![1, 2, 3], vec![2, 3], vec![3]]);
}
#[test]
fn extend_empty() {
use crate::classes::extend::extend;
let result =
extend::<VecBrand, _, _>(|v: Vec<i32>| v.iter().sum::<i32>(), Vec::<i32>::new());
assert_eq!(result, Vec::<i32>::new());
}
#[test]
fn extend_singleton() {
use crate::classes::extend::extend;
let result = extend::<VecBrand, _, _>(|v: Vec<i32>| v.iter().sum::<i32>(), vec![42]);
assert_eq!(result, vec![42]);
}
}