#[fp_macros::document_module]
mod inner {
use {
crate::{
Apply,
brands::{
Tuple2Brand,
Tuple2FirstAppliedBrand,
Tuple2SecondAppliedBrand,
},
classes::*,
dispatch::Ref,
impl_kind,
kinds::*,
},
core::ops::ControlFlow,
fp_macros::*,
};
impl_kind! {
for Tuple2Brand {
type Of<First, Second> = (First, Second);
}
}
impl_kind! {
for Tuple2Brand {
type Of<'a, First: 'a, Second: 'a>: 'a = (First, Second);
}
}
impl Bifunctor for Tuple2Brand {
#[document_signature]
#[document_type_parameters(
"The lifetime of the values.",
"The type of the first value.",
"The type of the mapped first value.",
"The type of the second value.",
"The type of the mapped second value."
)]
#[document_parameters(
"The function to apply to the first value.",
"The function to apply to the second value.",
"The tuple to map over."
)]
#[document_returns("A new tuple containing the mapped values.")]
#[document_examples]
fn bimap<'a, A: 'a, B: 'a, C: 'a, D: 'a>(
f: impl Fn(A) -> B + 'a,
g: impl Fn(C) -> D + 'a,
p: Apply!(<Self as Kind!( type Of<'a, A: 'a, B: 'a>: 'a; )>::Of<'a, A, C>),
) -> Apply!(<Self as Kind!( type Of<'a, A: 'a, B: 'a>: 'a; )>::Of<'a, B, D>) {
(f(p.0), g(p.1))
}
}
impl RefBifunctor for Tuple2Brand {
#[document_signature]
#[document_type_parameters(
"The lifetime of the values.",
"The type of the first value.",
"The type of the mapped first value.",
"The type of the second value.",
"The type of the mapped second value."
)]
#[document_parameters(
"The function to apply to a reference of the first value.",
"The function to apply to a reference of the second value.",
"The tuple to map over by reference."
)]
#[document_returns("A new tuple containing the mapped values.")]
#[document_examples]
fn ref_bimap<'a, A: 'a, B: 'a, C: 'a, D: 'a>(
f: impl Fn(&A) -> B + 'a,
g: impl Fn(&C) -> D + 'a,
p: &Apply!(<Self as Kind!( type Of<'a, A: 'a, B: 'a>: 'a; )>::Of<'a, A, C>),
) -> Apply!(<Self as Kind!( type Of<'a, A: 'a, B: 'a>: 'a; )>::Of<'a, B, D>) {
(f(&p.0), g(&p.1))
}
}
impl RefBifoldable for Tuple2Brand {
#[document_signature]
#[document_type_parameters(
"The lifetime of the values.",
"The brand of the cloneable function to use.",
"The type of the first element.",
"The type of the second element.",
"The accumulator type."
)]
#[document_parameters(
"The step function applied to a reference of the first element.",
"The step function applied to a reference of the second element.",
"The initial accumulator.",
"The tuple to fold by reference."
)]
#[document_returns("`f(&a, g(&b, z))`.")]
#[document_examples]
fn ref_bi_fold_right<'a, FnBrand: LiftFn + 'a, A: 'a + Clone, B: 'a + Clone, C: 'a>(
f: impl Fn(&A, C) -> C + 'a,
g: impl Fn(&B, C) -> C + 'a,
z: C,
p: &Apply!(<Self as Kind!( type Of<'a, A: 'a, B: 'a>: 'a; )>::Of<'a, A, B>),
) -> C {
f(&p.0, g(&p.1, z))
}
}
impl RefBitraversable for Tuple2Brand {
#[document_signature]
#[document_type_parameters(
"The lifetime of the values.",
"The brand of the cloneable function wrapper.",
"The type of the first element.",
"The type of the second element.",
"The output type for the first element.",
"The output type for the second element.",
"The applicative context."
)]
#[document_parameters(
"The function applied to a reference of the first element.",
"The function applied to a reference of the second element.",
"The tuple to traverse by reference."
)]
#[document_returns("`lift2(|c, d| (c, d), f(&a), g(&b))`.")]
#[document_examples]
fn ref_bi_traverse<
'a,
FnBrand,
A: 'a + Clone,
B: 'a + Clone,
C: 'a + Clone,
D: 'a + Clone,
F: Applicative,
>(
f: impl Fn(&A) -> Apply!(<F as Kind!( type Of<'a, T: 'a>: 'a; )>::Of<'a, C>) + 'a,
g: impl Fn(&B) -> Apply!(<F as Kind!( type Of<'a, T: 'a>: 'a; )>::Of<'a, D>) + 'a,
p: &Apply!(<Self as Kind!( type Of<'a, A: 'a, B: 'a>: 'a; )>::Of<'a, A, B>),
) -> Apply!(<F as Kind!( type Of<'a, T: 'a>: 'a; )>::Of<'a, Apply!(<Self as Kind!( type Of<'a, A: 'a, B: 'a>: 'a; )>::Of<'a, C, D>)>)
where
FnBrand: LiftFn + 'a,
Apply!(<Self as Kind!( type Of<'a, A: 'a, B: 'a>: 'a; )>::Of<'a, C, D>): Clone,
Apply!(<F as Kind!( type Of<'a, T: 'a>: 'a; )>::Of<'a, C>): Clone,
Apply!(<F as Kind!( type Of<'a, T: 'a>: 'a; )>::Of<'a, D>): Clone, {
F::lift2(|c, d| (c, d), f(&p.0), g(&p.1))
}
}
impl Bifoldable for Tuple2Brand {
#[document_signature]
#[document_type_parameters(
"The lifetime of the values.",
"The brand of the cloneable function to use.",
"The type of the first element.",
"The type of the second element.",
"The accumulator type."
)]
#[document_parameters(
"The step function applied to the first element.",
"The step function applied to the second element.",
"The initial accumulator.",
"The tuple to fold."
)]
#[document_returns("`f(a, g(b, z))`.")]
#[document_examples]
fn bi_fold_right<'a, FnBrand: CloneFn + 'a, A: 'a + Clone, B: 'a + Clone, C: 'a>(
f: impl Fn(A, C) -> C + 'a,
g: impl Fn(B, C) -> C + 'a,
z: C,
p: Apply!(<Self as Kind!( type Of<'a, A: 'a, B: 'a>: 'a; )>::Of<'a, A, B>),
) -> C {
let (a, b) = p;
f(a, g(b, z))
}
#[document_signature]
#[document_type_parameters(
"The lifetime of the values.",
"The brand of the cloneable function to use.",
"The type of the first element.",
"The type of the second element.",
"The accumulator type."
)]
#[document_parameters(
"The step function applied to the first element.",
"The step function applied to the second element.",
"The initial accumulator.",
"The tuple to fold."
)]
#[document_returns("`g(f(z, a), b)`.")]
#[document_examples]
fn bi_fold_left<'a, FnBrand: CloneFn + 'a, A: 'a + Clone, B: 'a + Clone, C: 'a>(
f: impl Fn(C, A) -> C + 'a,
g: impl Fn(C, B) -> C + 'a,
z: C,
p: Apply!(<Self as Kind!( type Of<'a, A: 'a, B: 'a>: 'a; )>::Of<'a, A, B>),
) -> C {
let (a, b) = p;
g(f(z, a), b)
}
#[document_signature]
#[document_type_parameters(
"The lifetime of the values.",
"The brand of the cloneable function to use.",
"The type of the first element.",
"The type of the second element.",
"The monoid type."
)]
#[document_parameters(
"The function mapping the first element to the monoid.",
"The function mapping the second element to the monoid.",
"The tuple to fold."
)]
#[document_returns("`M::append(f(a), g(b))`.")]
#[document_examples]
fn bi_fold_map<'a, FnBrand: CloneFn + 'a, A: 'a + Clone, B: 'a + Clone, M>(
f: impl Fn(A) -> M + 'a,
g: impl Fn(B) -> M + 'a,
p: Apply!(<Self as Kind!( type Of<'a, A: 'a, B: 'a>: 'a; )>::Of<'a, A, B>),
) -> M
where
M: Monoid + 'a, {
let (a, b) = p;
M::append(f(a), g(b))
}
}
impl Bitraversable for Tuple2Brand {
#[document_signature]
#[document_type_parameters(
"The lifetime of the values.",
"The type of the first element.",
"The type of the second element.",
"The output type for the first element.",
"The output type for the second element.",
"The applicative context."
)]
#[document_parameters(
"The function applied to the first element.",
"The function applied to the second element.",
"The tuple to traverse."
)]
#[document_returns("`lift2(|c, d| (c, d), f(a), g(b))`.")]
#[document_examples]
fn bi_traverse<
'a,
A: 'a + Clone,
B: 'a + Clone,
C: 'a + Clone,
D: 'a + Clone,
F: Applicative,
>(
f: impl Fn(A) -> Apply!(<F as Kind!( type Of<'a, T: 'a>: 'a; )>::Of<'a, C>) + 'a,
g: impl Fn(B) -> Apply!(<F as Kind!( type Of<'a, T: 'a>: 'a; )>::Of<'a, D>) + 'a,
p: Apply!(<Self as Kind!( type Of<'a, A: 'a, B: 'a>: 'a; )>::Of<'a, A, B>),
) -> Apply!(<F as Kind!( type Of<'a, T: 'a>: 'a; )>::Of<'a, Apply!(<Self as Kind!( type Of<'a, A: 'a, B: 'a>: 'a; )>::Of<'a, C, D>)>)
{
let (a, b) = p;
F::lift2(|c, d| (c, d), f(a), g(b))
}
}
impl_kind! {
#[no_inferable_brand]
impl<First: 'static> for Tuple2FirstAppliedBrand<First> {
type Of<'a, A: 'a>: 'a = (First, A);
}
}
#[document_type_parameters("The type of the first value in the tuple.")]
impl<First: 'static> Functor for Tuple2FirstAppliedBrand<First> {
#[document_signature]
#[document_type_parameters(
"The lifetime of the values.",
"The type of the second value.",
"The type of the result of applying the function."
)]
#[document_parameters(
"The function to apply to the second value.",
"The tuple to map over."
)]
#[document_returns(
"A new tuple containing the result of applying the function to the second value."
)]
#[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.0, func(fa.1))
}
}
#[document_type_parameters("The type of the first value in the tuple.")]
impl<First: Clone + 'static> Lift for Tuple2FirstAppliedBrand<First>
where
First: Semigroup,
{
#[document_signature]
#[document_type_parameters(
"The lifetime of the values.",
"The type of the first second value.",
"The type of the second second value.",
"The type of the result second value."
)]
#[document_parameters(
"The binary function to apply to the second values.",
"The first tuple.",
"The second tuple."
)]
#[document_returns(
"A new tuple where the first values are combined using `Semigroup::append` and the second values are combined using `f`."
)]
#[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, {
(Semigroup::append(fa.0, fb.0), func(fa.1, fb.1))
}
}
#[document_type_parameters("The type of the first value in the tuple.")]
impl<First: Clone + 'static> Pointed for Tuple2FirstAppliedBrand<First>
where
First: Monoid,
{
#[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 tuple containing the empty value of the first type and `a`.")]
#[document_examples]
fn pure<'a, A: 'a>(a: A) -> Apply!(<Self as Kind!( type Of<'a, T: 'a>: 'a; )>::Of<'a, A>) {
(Monoid::empty(), a)
}
}
#[document_type_parameters("The type of the first value in the tuple.")]
impl<First: Clone + Semigroup + 'static> ApplyFirst for Tuple2FirstAppliedBrand<First> {}
#[document_type_parameters("The type of the first value in the tuple.")]
impl<First: Clone + Semigroup + 'static> ApplySecond for Tuple2FirstAppliedBrand<First> {}
#[document_type_parameters("The type of the first value in the tuple.")]
impl<First: Clone + 'static> Semiapplicative for Tuple2FirstAppliedBrand<First>
where
First: Semigroup,
{
#[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 tuple containing the function.",
"The tuple containing the value."
)]
#[document_returns(
"A new tuple where the first values are combined and the function is applied to the second value."
)]
#[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>) {
(Semigroup::append(ff.0, fa.0), ff.1(fa.1))
}
}
#[document_type_parameters("The type of the first value in the tuple.")]
impl<First: Clone + 'static> Semimonad for Tuple2FirstAppliedBrand<First>
where
First: Semigroup,
{
#[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 tuple.", "The function to apply to the second value.")]
#[document_returns("A new tuple where the first values are combined.")]
#[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>) {
let (first, second) = ma;
let (next_first, next_second) = func(second);
(Semigroup::append(first, next_first), next_second)
}
}
#[document_type_parameters("The type of the first value in the tuple.")]
impl<First: Clone + 'static> MonadRec for Tuple2FirstAppliedBrand<First>
where
First: Monoid,
{
#[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 tuple with the accumulated first value and the result of the computation."
)]
#[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 acc: First = Monoid::empty();
let mut current = initial;
loop {
let (first, step) = func(current);
acc = Semigroup::append(acc, first);
match step {
ControlFlow::Continue(next) => current = next,
ControlFlow::Break(b) => return (acc, b),
}
}
}
}
#[document_type_parameters("The type of the first value in the tuple.")]
impl<First: 'static> Foldable for Tuple2FirstAppliedBrand<First> {
#[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 tuple to fold.")]
#[document_returns("`func(a, 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, {
func(fa.1, 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 tuple to fold."
)]
#[document_returns("`func(initial, a)`.")]
#[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, {
func(initial, fa.1)
}
#[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 tuple to fold.")]
#[document_returns("`func(a)`.")]
#[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, {
func(fa.1)
}
}
#[document_type_parameters("The type of the first value in the tuple.")]
impl<First: Clone + 'static> Traversable for Tuple2FirstAppliedBrand<First> {
#[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 tuple to traverse."
)]
#[document_returns("The tuple 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, {
let (first, second) = ta;
F::map(move |b| (first.clone(), b), func(second))
}
#[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 tuple containing the applicative value.")]
#[document_returns("The tuple 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 (first, second) = ta;
F::map(move |a| (first.clone(), a), second)
}
}
#[document_type_parameters("The type of the first value in the tuple.")]
impl<First: Clone + 'static> RefFunctor for Tuple2FirstAppliedBrand<First> {
#[document_signature]
#[document_type_parameters("The lifetime.", "The input type.", "The output type.")]
#[document_parameters("The function.", "The tuple.")]
#[document_returns("A new tuple with the mapped second value.")]
#[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.0.clone(), func(&fa.1))
}
}
#[document_type_parameters("The type of the first value in the tuple.")]
impl<First: Clone + 'static> RefFoldable for Tuple2FirstAppliedBrand<First> {
#[document_signature]
#[document_type_parameters(
"The lifetime.",
"The brand.",
"The element type.",
"The monoid type."
)]
#[document_parameters("The mapping function.", "The tuple.")]
#[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, {
func(&fa.1)
}
}
#[document_type_parameters("The type of the first value in the tuple.")]
impl<First: Clone + 'static> RefTraversable for Tuple2FirstAppliedBrand<First> {
#[document_signature]
#[document_type_parameters(
"The lifetime.",
"The brand.",
"The input type.",
"The output type.",
"The applicative."
)]
#[document_parameters("The function.", "The tuple.")]
#[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, {
let first = ta.0.clone();
F::map(move |b| (first.clone(), b), func(&ta.1))
}
}
#[document_type_parameters("The type of the first value in the tuple.")]
impl<First: Clone + 'static> RefPointed for Tuple2FirstAppliedBrand<First>
where
First: Monoid,
{
#[document_signature]
#[document_type_parameters("The lifetime.", "The value type.")]
#[document_parameters("The reference to wrap.")]
#[document_returns("A tuple containing `Monoid::empty()` and 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>) {
(Monoid::empty(), a.clone())
}
}
#[document_type_parameters("The type of the first value in the tuple.")]
impl<First: Clone + 'static> RefLift for Tuple2FirstAppliedBrand<First>
where
First: Semigroup,
{
#[document_signature]
#[document_type_parameters("The lifetime.", "First input.", "Second input.", "Output.")]
#[document_parameters("The binary function.", "The first tuple.", "The second tuple.")]
#[document_returns("A tuple with combined first values and the function result.")]
#[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>) {
(Semigroup::append(fa.0.clone(), fb.0.clone()), func(&fa.1, &fb.1))
}
}
#[document_type_parameters("The type of the first value in the tuple.")]
impl<First: Clone + 'static> RefSemiapplicative for Tuple2FirstAppliedBrand<First>
where
First: Semigroup,
{
#[document_signature]
#[document_type_parameters(
"The lifetime.",
"The function brand.",
"The input type.",
"The output type."
)]
#[document_parameters(
"The tuple containing the function.",
"The tuple containing the value."
)]
#[document_returns("A tuple with combined first values and the function result.")]
#[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>) {
(Semigroup::append(ff.0.clone(), fa.0.clone()), (*ff.1)(&fa.1))
}
}
#[document_type_parameters("The type of the first value in the tuple.")]
impl<First: Clone + 'static> RefSemimonad for Tuple2FirstAppliedBrand<First>
where
First: Semigroup,
{
#[document_signature]
#[document_type_parameters("The lifetime.", "The input type.", "The output type.")]
#[document_parameters("The input tuple.", "The function to apply by reference.")]
#[document_returns("A tuple with combined first values.")]
#[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>) {
let (next_first, next_second) = f(&fa.1);
(Semigroup::append(fa.0.clone(), next_first), next_second)
}
}
impl_kind! {
#[no_inferable_brand]
impl<Second: 'static> for Tuple2SecondAppliedBrand<Second> {
type Of<'a, A: 'a>: 'a = (A, Second);
}
}
#[document_type_parameters("The type of the second value in the tuple.")]
impl<Second: 'static> Functor for Tuple2SecondAppliedBrand<Second> {
#[document_signature]
#[document_type_parameters(
"The lifetime of the values.",
"The type of the first value.",
"The type of the result of applying the function."
)]
#[document_parameters(
"The function to apply to the first value.",
"The tuple to map over."
)]
#[document_returns(
"A new tuple containing the result of applying the function to the first value."
)]
#[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>) {
(func(fa.0), fa.1)
}
}
#[document_type_parameters("The type of the second value in the tuple.")]
impl<Second: Clone + 'static> Lift for Tuple2SecondAppliedBrand<Second>
where
Second: Semigroup,
{
#[document_signature]
#[document_type_parameters(
"The lifetime of the values.",
"The type of the first first value.",
"The type of the second first value.",
"The type of the result first value."
)]
#[document_parameters(
"The binary function to apply to the first values.",
"The first tuple.",
"The second tuple."
)]
#[document_returns(
"A new tuple where the first values are combined using `f` and the second values are combined using `Semigroup::append`."
)]
#[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, {
(func(fa.0, fb.0), Semigroup::append(fa.1, fb.1))
}
}
#[document_type_parameters("The type of the second value in the tuple.")]
impl<Second: Clone + 'static> Pointed for Tuple2SecondAppliedBrand<Second>
where
Second: Monoid,
{
#[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 tuple containing `a` and the empty value of the second type.")]
#[document_examples]
fn pure<'a, A: 'a>(a: A) -> Apply!(<Self as Kind!( type Of<'a, T: 'a>: 'a; )>::Of<'a, A>) {
(a, Monoid::empty())
}
}
#[document_type_parameters("The type of the second value in the tuple.")]
impl<Second: Clone + Semigroup + 'static> ApplyFirst for Tuple2SecondAppliedBrand<Second> {}
#[document_type_parameters("The type of the second value in the tuple.")]
impl<Second: Clone + Semigroup + 'static> ApplySecond for Tuple2SecondAppliedBrand<Second> {}
#[document_type_parameters("The type of the second value in the tuple.")]
impl<Second: Clone + 'static> Semiapplicative for Tuple2SecondAppliedBrand<Second>
where
Second: Semigroup,
{
#[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 tuple containing the function.",
"The tuple containing the value."
)]
#[document_returns(
"A new tuple where the function is applied to the first value and the second values are combined."
)]
#[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>) {
(ff.0(fa.0), Semigroup::append(ff.1, fa.1))
}
}
#[document_type_parameters("The type of the second value in the tuple.")]
impl<Second: Clone + 'static> Semimonad for Tuple2SecondAppliedBrand<Second>
where
Second: Semigroup,
{
#[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 tuple.", "The function to apply to the first value.")]
#[document_returns("A new tuple where the second values are combined.")]
#[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>) {
let (first, second) = ma;
let (next_first, next_second) = func(first);
(next_first, Semigroup::append(second, next_second))
}
}
#[document_type_parameters("The type of the second value in the tuple.")]
impl<Second: Clone + 'static> MonadRec for Tuple2SecondAppliedBrand<Second>
where
Second: Monoid,
{
#[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 tuple with the result of the computation and the accumulated second value."
)]
#[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 acc: Second = Monoid::empty();
let mut current = initial;
loop {
let (step, second) = func(current);
acc = Semigroup::append(acc, second);
match step {
ControlFlow::Continue(next) => current = next,
ControlFlow::Break(b) => return (b, acc),
}
}
}
}
#[document_type_parameters("The type of the second value in the tuple.")]
impl<Second: 'static> Foldable for Tuple2SecondAppliedBrand<Second> {
#[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 tuple to fold.")]
#[document_returns("`func(a, 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, {
func(fa.0, 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 folding function.", "The initial value.", "The tuple to fold.")]
#[document_returns("`func(initial, a)`.")]
#[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, {
func(initial, fa.0)
}
#[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 tuple to fold.")]
#[document_returns("`func(a)`.")]
#[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, {
func(fa.0)
}
}
#[document_type_parameters("The type of the second value in the tuple.")]
impl<Second: Clone + 'static> Traversable for Tuple2SecondAppliedBrand<Second> {
#[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.", "The tuple to traverse.")]
#[document_returns("The tuple 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, {
let (first, second) = ta;
F::map(move |b| (b, second.clone()), func(first))
}
#[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 tuple containing the applicative value.")]
#[document_returns("The tuple 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 (first, second) = ta;
F::map(move |a| (a, second.clone()), first)
}
}
#[document_type_parameters("The type of the second value in the tuple.")]
impl<Second: Clone + 'static> RefFunctor for Tuple2SecondAppliedBrand<Second> {
#[document_signature]
#[document_type_parameters("The lifetime.", "The input type.", "The output type.")]
#[document_parameters("The function.", "The tuple.")]
#[document_returns("A new tuple with the mapped first value.")]
#[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>) {
(func(&fa.0), fa.1.clone())
}
}
#[document_type_parameters("The type of the second value in the tuple.")]
impl<Second: Clone + 'static> RefFoldable for Tuple2SecondAppliedBrand<Second> {
#[document_signature]
#[document_type_parameters(
"The lifetime.",
"The brand.",
"The element type.",
"The monoid type."
)]
#[document_parameters("The mapping function.", "The tuple.")]
#[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, {
func(&fa.0)
}
}
#[document_type_parameters("The type of the second value in the tuple.")]
impl<Second: Clone + 'static> RefTraversable for Tuple2SecondAppliedBrand<Second> {
#[document_signature]
#[document_type_parameters(
"The lifetime.",
"The brand.",
"The input type.",
"The output type.",
"The applicative."
)]
#[document_parameters("The function.", "The tuple.")]
#[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, {
let second = ta.1.clone();
F::map(move |a| (a, second.clone()), func(&ta.0))
}
}
#[document_type_parameters("The type of the second value in the tuple.")]
impl<Second: Clone + 'static> RefPointed for Tuple2SecondAppliedBrand<Second>
where
Second: Monoid,
{
#[document_signature]
#[document_type_parameters("The lifetime.", "The value type.")]
#[document_parameters("The reference to wrap.")]
#[document_returns("A tuple containing a clone of the value and `Monoid::empty()`.")]
#[document_examples]
fn ref_pure<'a, A: Clone + 'a>(
a: &A
) -> Apply!(<Self as Kind!( type Of<'a, T: 'a>: 'a; )>::Of<'a, A>) {
(a.clone(), Monoid::empty())
}
}
#[document_type_parameters("The type of the second value in the tuple.")]
impl<Second: Clone + 'static> RefLift for Tuple2SecondAppliedBrand<Second>
where
Second: Semigroup,
{
#[document_signature]
#[document_type_parameters("The lifetime.", "First input.", "Second input.", "Output.")]
#[document_parameters("The binary function.", "The first tuple.", "The second tuple.")]
#[document_returns("A tuple with the function result and combined second values.")]
#[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>) {
(func(&fa.0, &fb.0), Semigroup::append(fa.1.clone(), fb.1.clone()))
}
}
#[document_type_parameters("The type of the second value in the tuple.")]
impl<Second: Clone + 'static> RefSemiapplicative for Tuple2SecondAppliedBrand<Second>
where
Second: Semigroup,
{
#[document_signature]
#[document_type_parameters(
"The lifetime.",
"The function brand.",
"The input type.",
"The output type."
)]
#[document_parameters(
"The tuple containing the function.",
"The tuple containing the value."
)]
#[document_returns("A tuple with the function result and combined second values.")]
#[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>) {
((*ff.0)(&fa.0), Semigroup::append(ff.1.clone(), fa.1.clone()))
}
}
#[document_type_parameters("The type of the second value in the tuple.")]
impl<Second: Clone + 'static> RefSemimonad for Tuple2SecondAppliedBrand<Second>
where
Second: Semigroup,
{
#[document_signature]
#[document_type_parameters("The lifetime.", "The input type.", "The output type.")]
#[document_parameters("The input tuple.", "The function to apply by reference.")]
#[document_returns("A tuple with combined second values.")]
#[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>) {
let (next_first, next_second) = f(&fa.0);
(next_first, Semigroup::append(fa.1.clone(), next_second))
}
}
}
#[cfg(test)]
mod tests {
use {
crate::{
brands::*,
classes::*,
functions::*,
},
core::ops::ControlFlow,
quickcheck_macros::quickcheck,
};
#[test]
fn test_bimap() {
let x = (1, 5);
assert_eq!(
explicit::bimap::<Tuple2Brand, _, _, _, _, _, _>((|a| a + 1, |b| b * 2), x),
(2, 10)
);
}
#[quickcheck]
fn bifunctor_identity(
first: String,
second: i32,
) -> bool {
let x = (first, second);
explicit::bimap::<Tuple2Brand, _, _, _, _, _, _>((identity, identity), x.clone()) == x
}
#[quickcheck]
fn bifunctor_composition(
first: i32,
second: i32,
) -> bool {
let x = (first, second);
let f = |x: i32| x.wrapping_add(1);
let g = |x: i32| x.wrapping_mul(2);
let h = |x: i32| x.wrapping_sub(1);
let i = |x: i32| if x == 0 { 0 } else { x.wrapping_div(2) };
explicit::bimap::<Tuple2Brand, _, _, _, _, _, _>((compose(f, g), compose(h, i)), x)
== explicit::bimap::<Tuple2Brand, _, _, _, _, _, _>(
(f, h),
explicit::bimap::<Tuple2Brand, _, _, _, _, _, _>((g, i), x),
)
}
#[quickcheck]
fn functor_identity(
first: String,
second: i32,
) -> bool {
let x = (first, second);
explicit::map::<Tuple2FirstAppliedBrand<String>, _, _, _, _>(identity, x.clone()) == x
}
#[quickcheck]
fn functor_composition(
first: String,
second: i32,
) -> bool {
let x = (first, second);
let f = |x: i32| x.wrapping_add(1);
let g = |x: i32| x.wrapping_mul(2);
explicit::map::<Tuple2FirstAppliedBrand<String>, _, _, _, _>(compose(f, g), x.clone())
== explicit::map::<Tuple2FirstAppliedBrand<String>, _, _, _, _>(
f,
explicit::map::<Tuple2FirstAppliedBrand<String>, _, _, _, _>(g, x),
)
}
#[quickcheck]
fn applicative_identity(
first: String,
second: i32,
) -> bool {
let v = (first, second);
apply::<RcFnBrand, Tuple2FirstAppliedBrand<String>, _, _>(
pure::<Tuple2FirstAppliedBrand<String>, _>(<RcFnBrand as LiftFn>::new(identity)),
v.clone(),
) == v
}
#[quickcheck]
fn applicative_homomorphism(x: i32) -> bool {
let f = |x: i32| x.wrapping_mul(2);
apply::<RcFnBrand, Tuple2FirstAppliedBrand<String>, _, _>(
pure::<Tuple2FirstAppliedBrand<String>, _>(<RcFnBrand as LiftFn>::new(f)),
pure::<Tuple2FirstAppliedBrand<String>, _>(x),
) == pure::<Tuple2FirstAppliedBrand<String>, _>(f(x))
}
#[quickcheck]
fn applicative_composition(
w_first: String,
w_second: i32,
u_seed: i32,
v_seed: i32,
) -> bool {
let w = (w_first, w_second);
let u_fn = <RcFnBrand as LiftFn>::new(move |x: i32| x.wrapping_add(u_seed));
let u = pure::<Tuple2FirstAppliedBrand<String>, _>(u_fn);
let v_fn = <RcFnBrand as LiftFn>::new(move |x: i32| x.wrapping_mul(v_seed));
let v = pure::<Tuple2FirstAppliedBrand<String>, _>(v_fn);
let vw = apply::<RcFnBrand, Tuple2FirstAppliedBrand<String>, _, _>(v.clone(), w.clone());
let rhs = apply::<RcFnBrand, Tuple2FirstAppliedBrand<String>, _, _>(u.clone(), vw);
let compose_fn = <RcFnBrand as LiftFn>::new(|f: std::rc::Rc<dyn Fn(i32) -> i32>| {
let f = f.clone();
<RcFnBrand as LiftFn>::new(move |g: std::rc::Rc<dyn Fn(i32) -> i32>| {
let f = f.clone();
let g = g.clone();
<RcFnBrand as LiftFn>::new(move |x| f(g(x)))
})
});
let pure_compose = pure::<Tuple2FirstAppliedBrand<String>, _>(compose_fn);
let u_applied = apply::<RcFnBrand, Tuple2FirstAppliedBrand<String>, _, _>(pure_compose, u);
let uv = apply::<RcFnBrand, Tuple2FirstAppliedBrand<String>, _, _>(u_applied, v);
let lhs = apply::<RcFnBrand, Tuple2FirstAppliedBrand<String>, _, _>(uv, w);
lhs == rhs
}
#[quickcheck]
fn applicative_interchange(
y: i32,
u_seed: i32,
) -> bool {
let f = move |x: i32| x.wrapping_mul(u_seed);
let u = pure::<Tuple2FirstAppliedBrand<String>, _>(<RcFnBrand as LiftFn>::new(f));
let lhs = apply::<RcFnBrand, Tuple2FirstAppliedBrand<String>, _, _>(
u.clone(),
pure::<Tuple2FirstAppliedBrand<String>, _>(y),
);
let rhs_fn = <RcFnBrand as LiftFn>::new(move |f: std::rc::Rc<dyn Fn(i32) -> i32>| f(y));
let rhs = apply::<RcFnBrand, Tuple2FirstAppliedBrand<String>, _, _>(
pure::<Tuple2FirstAppliedBrand<String>, _>(rhs_fn),
u,
);
lhs == rhs
}
#[quickcheck]
fn monad_left_identity(a: i32) -> bool {
let f = |x: i32| ("f".to_string(), x.wrapping_mul(2));
explicit::bind::<Tuple2FirstAppliedBrand<String>, _, _, _, _>(
pure::<Tuple2FirstAppliedBrand<String>, _>(a),
f,
) == f(a)
}
#[quickcheck]
fn monad_right_identity(
first: String,
second: i32,
) -> bool {
let m = (first, second);
explicit::bind::<Tuple2FirstAppliedBrand<String>, _, _, _, _>(
m.clone(),
pure::<Tuple2FirstAppliedBrand<String>, _>,
) == m
}
#[quickcheck]
fn monad_associativity(
first: String,
second: i32,
) -> bool {
let m = (first, second);
let f = |x: i32| ("f".to_string(), x.wrapping_mul(2));
let g = |x: i32| ("g".to_string(), x.wrapping_add(1));
explicit::bind::<Tuple2FirstAppliedBrand<String>, _, _, _, _>(
explicit::bind::<Tuple2FirstAppliedBrand<String>, _, _, _, _>(m.clone(), f),
g,
) == explicit::bind::<Tuple2FirstAppliedBrand<String>, _, _, _, _>(m, |x| {
explicit::bind::<Tuple2FirstAppliedBrand<String>, _, _, _, _>(f(x), g)
})
}
#[quickcheck]
fn monad_rec_first_identity(x: i32) -> bool {
tail_rec_m::<Tuple2FirstAppliedBrand<String>, _, _>(
|a| (String::new(), ControlFlow::Break(a)),
x,
) == pure::<Tuple2FirstAppliedBrand<String>, _>(x)
}
#[test]
fn monad_rec_first_accumulation() {
let result = tail_rec_m::<Tuple2FirstAppliedBrand<String>, _, _>(
|n: i32| {
if n < 3 {
(format!("{n},"), ControlFlow::Continue(n + 1))
} else {
(format!("{n}"), ControlFlow::Break(n))
}
},
0,
);
assert_eq!(result, ("0,1,2,3".to_string(), 3));
}
#[test]
fn monad_rec_first_stack_safety() {
let iterations: i64 = 200_000;
let result = tail_rec_m::<Tuple2FirstAppliedBrand<String>, _, _>(
|acc| {
if acc < iterations {
(String::new(), ControlFlow::Continue(acc + 1))
} else {
(String::new(), ControlFlow::Break(acc))
}
},
0i64,
);
assert_eq!(result, (String::new(), iterations));
}
#[quickcheck]
fn monad_rec_second_identity(x: i32) -> bool {
tail_rec_m::<Tuple2SecondAppliedBrand<String>, _, _>(
|a| (ControlFlow::Break(a), String::new()),
x,
) == pure::<Tuple2SecondAppliedBrand<String>, _>(x)
}
#[test]
fn monad_rec_second_accumulation() {
let result = tail_rec_m::<Tuple2SecondAppliedBrand<String>, _, _>(
|n: i32| {
if n < 3 {
(ControlFlow::Continue(n + 1), format!("{n},"))
} else {
(ControlFlow::Break(n), format!("{n}"))
}
},
0,
);
assert_eq!(result, (3, "0,1,2,3".to_string()));
}
#[test]
fn monad_rec_second_stack_safety() {
let iterations: i64 = 200_000;
let result = tail_rec_m::<Tuple2SecondAppliedBrand<String>, _, _>(
|acc| {
if acc < iterations {
(ControlFlow::Continue(acc + 1), String::new())
} else {
(ControlFlow::Break(acc), String::new())
}
},
0i64,
);
assert_eq!(result, (iterations, String::new()));
}
}