#[fp_macros::document_module]
mod inner {
use {
crate::{
Apply,
brands::IdentityBrand,
classes::*,
dispatch::Ref,
impl_kind,
kinds::*,
},
core::ops::ControlFlow,
fp_macros::*,
};
#[document_type_parameters("The type of the wrapped value.")]
#[cfg_attr(feature = "serde", derive(serde::Serialize, serde::Deserialize))]
#[derive(Clone, Copy, Debug, Default, Eq, Hash, Ord, PartialEq, PartialOrd)]
pub struct Identity<A>(
pub A,
);
impl_kind! {
for IdentityBrand {
type Of<'a, A: 'a>: 'a = Identity<A>;
}
}
#[document_type_parameters("The type of the wrapped value.")]
#[document_parameters("The identity instance.")]
impl<A> Identity<A> {
#[document_signature]
#[document_type_parameters("The type of the result of applying the function.")]
#[document_parameters("The function to apply.")]
#[document_returns("A new identity containing the result of applying the function.")]
#[document_examples]
pub fn map<B>(
self,
f: impl FnOnce(A) -> B,
) -> Identity<B> {
Identity(f(self.0))
}
#[document_signature]
#[document_type_parameters(
"The type of the other identity's value.",
"The return type of the function."
)]
#[document_parameters("The other identity.", "The binary function to apply.")]
#[document_returns("A new identity containing the result of applying the function.")]
#[document_examples]
pub fn lift2<B, C>(
self,
other: Identity<B>,
f: impl FnOnce(A, B) -> C,
) -> Identity<C> {
Identity(f(self.0, other.0))
}
#[document_signature]
#[document_type_parameters("The return type of the wrapped function.")]
#[document_parameters("The identity containing the function.")]
#[document_returns("A new identity containing the result.")]
#[document_examples]
pub fn apply<B>(
self,
ff: Identity<impl FnOnce(A) -> B>,
) -> Identity<B> {
Identity(ff.0(self.0))
}
#[document_signature]
#[document_type_parameters("The type of the result of the chained computation.")]
#[document_parameters("The function to apply to the value inside the identity.")]
#[document_returns("The result of applying `f` to the value.")]
#[document_examples]
pub fn bind<B>(
self,
f: impl FnOnce(A) -> Identity<B>,
) -> Identity<B> {
f(self.0)
}
#[document_signature]
#[document_type_parameters("The type of the accumulator.")]
#[document_parameters(
"The function to apply to the element and the accumulator.",
"The initial value of the accumulator."
)]
#[document_returns("The final accumulator value.")]
#[document_examples]
pub fn fold_right<B>(
self,
f: impl FnOnce(A, B) -> B,
initial: B,
) -> B {
f(self.0, initial)
}
#[document_signature]
#[document_type_parameters("The type of the accumulator.")]
#[document_parameters(
"The function to apply to the accumulator and the element.",
"The initial value of the accumulator."
)]
#[document_returns("The final accumulator value.")]
#[document_examples]
pub fn fold_left<B>(
self,
f: impl FnOnce(B, A) -> B,
initial: B,
) -> B {
f(initial, self.0)
}
#[document_signature]
#[document_type_parameters("The monoid type.")]
#[document_parameters("The mapping function.")]
#[document_returns("The monoid value.")]
#[document_examples]
pub fn fold_map<M>(
self,
f: impl FnOnce(A) -> M,
) -> M {
f(self.0)
}
}
#[document_type_parameters("The lifetime of the values.", "The type of the wrapped value.")]
#[document_parameters("The identity instance.")]
impl<'a, A: 'a> Identity<A> {
#[document_signature]
#[document_type_parameters(
"The type of the elements in the resulting identity.",
"The applicative context."
)]
#[document_parameters(
"The function to apply, returning a value in an applicative context."
)]
#[document_returns("The identity wrapped in the applicative context.")]
#[document_examples]
pub fn traverse<B: 'a + Clone, F: Applicative>(
self,
f: impl Fn(A) -> Apply!(<F as Kind!( type Of<'a, T: 'a>: 'a; )>::Of<'a, B>) + 'a,
) -> Apply!(<F as Kind!( type Of<'a, T: 'a>: 'a; )>::Of<'a, Identity<B>>)
where
Identity<B>: Clone, {
F::map(|b| Identity(b), f(self.0))
}
#[document_signature]
#[document_type_parameters(
"The inner type wrapped in the applicative context.",
"The applicative context."
)]
#[document_returns("The identity wrapped in the applicative context.")]
#[document_examples]
pub fn sequence<InnerA: 'a + Clone, F: Applicative>(
self
) -> Apply!(<F as Kind!( type Of<'a, T: 'a>: 'a; )>::Of<'a, Identity<InnerA>>)
where
A: Into<Apply!(<F as Kind!( type Of<'a, T: 'a>: 'a; )>::Of<'a, InnerA>)>,
Identity<InnerA>: Clone, {
F::map(|a| Identity(a), self.0.into())
}
}
impl Functor for IdentityBrand {
#[document_signature]
#[document_type_parameters(
"The lifetime of the value.",
"The type of the value inside the identity.",
"The type of the result of applying the function."
)]
#[document_parameters("The function to apply.", "The identity to map over.")]
#[document_returns("A new identity containing the result 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.map(func)
}
}
impl Lift for IdentityBrand {
#[document_signature]
#[document_type_parameters(
"The lifetime of the values.",
"The type of the first identity's value.",
"The type of the second identity's value.",
"The return type of the function."
)]
#[document_parameters(
"The binary function to apply.",
"The first identity.",
"The second identity."
)]
#[document_returns("A new identity containing the result of applying the function.")]
#[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.lift2(fb, func)
}
}
impl Pointed for IdentityBrand {
#[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("An identity containing the value.")]
#[document_examples]
fn pure<'a, A: 'a>(a: A) -> Apply!(<Self as Kind!( type Of<'a, T: 'a>: 'a; )>::Of<'a, A>) {
Identity(a) }
}
impl ApplyFirst for IdentityBrand {}
impl ApplySecond for IdentityBrand {}
impl Semiapplicative for IdentityBrand {
#[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 identity containing the function.",
"The identity containing the value."
)]
#[document_returns("A new identity containing the result of applying the function.")]
#[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>) {
fa.apply(ff.map(|f| move |a| f(a)))
}
}
impl Semimonad for IdentityBrand {
#[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 identity.",
"The function to apply to the value inside the identity."
)]
#[document_returns("The result of applying `f` to the value.")]
#[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.bind(func)
}
}
impl Foldable for IdentityBrand {
#[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 each element and the accumulator.",
"The initial value of the accumulator.",
"The identity to fold."
)]
#[document_returns("The final accumulator value.")]
#[document_examples]
fn fold_right<'a, FnBrand, A: 'a, 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, {
fa.fold_right(func, 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 structure to fold."
)]
#[document_returns("The final accumulator value.")]
#[document_examples]
fn fold_left<'a, FnBrand, A: 'a, 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, {
fa.fold_left(func, 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 identity to fold.")]
#[document_returns("The monoid value.")]
#[document_examples]
fn fold_map<'a, FnBrand, A: 'a, 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, {
fa.fold_map(func)
}
}
impl Traversable for IdentityBrand {
#[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 identity to traverse."
)]
#[document_returns("The identity 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, {
ta.traverse::<B, F>(func)
}
#[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 identity 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, {
ta.traverse::<A, F>(|a| a)
}
}
impl MonadRec for IdentityBrand {
#[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("An identity containing 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 current = initial;
loop {
match func(current).0 {
ControlFlow::Continue(next) => current = next,
ControlFlow::Break(b) => return Identity(b),
}
}
}
}
impl Extract for IdentityBrand {
#[document_signature]
#[document_type_parameters(
"The lifetime of the value.",
"The type of the value inside the identity."
)]
#[document_parameters("The identity to extract from.")]
#[document_returns("The inner value.")]
#[document_examples]
fn extract<'a, A: 'a>(
fa: Apply!(<Self as Kind!( type Of<'a, T: 'a>: 'a; )>::Of<'a, A>)
) -> A {
fa.0
}
}
impl Extend for IdentityBrand {
#[document_signature]
#[document_type_parameters(
"The lifetime of the values.",
"The type of the value inside the identity.",
"The result type of the extension function."
)]
#[document_parameters(
"The function that consumes an `Identity` and produces a value.",
"The identity to extend over."
)]
#[document_returns("A new identity containing the result of applying the function.")]
#[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>) {
Identity(f(wa))
}
}
impl RefFunctor for IdentityBrand {
#[document_signature]
#[document_type_parameters(
"The lifetime of the value.",
"The type of the wrapped value.",
"The type of the resulting value."
)]
#[document_parameters(
"The function to apply to the value reference.",
"The identity to map over."
)]
#[document_returns("A new identity containing the result.")]
#[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>) {
Identity(func(&fa.0))
}
}
impl RefFoldable for IdentityBrand {
#[document_signature]
#[document_type_parameters(
"The lifetime of the value.",
"The brand of the cloneable function wrapper.",
"The type of the wrapped value.",
"The monoid type."
)]
#[document_parameters(
"The function to map the value reference to a monoid.",
"The identity to fold."
)]
#[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)
}
}
impl RefTraversable for IdentityBrand {
#[document_signature]
#[document_type_parameters(
"The lifetime of the value.",
"The brand of the cloneable function wrapper.",
"The type of the wrapped value.",
"The type of the resulting value.",
"The applicative functor brand."
)]
#[document_parameters(
"The function to apply to the value reference.",
"The identity to traverse."
)]
#[document_returns("The result in the applicative context.")]
#[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, {
F::map(Identity, func(&ta.0))
}
}
impl WithIndex for IdentityBrand {
type Index = ();
}
impl FunctorWithIndex for IdentityBrand {
#[document_signature]
#[document_type_parameters("The lifetime.", "The input type.", "The output type.")]
#[document_parameters("The function to apply with index.", "The Identity value.")]
#[document_returns("The transformed Identity value.")]
#[document_examples]
fn 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>) {
Identity(func((), fa.0))
}
}
impl FoldableWithIndex for IdentityBrand {
#[document_signature]
#[document_type_parameters(
"The lifetime.",
"The brand of the cloneable function to use.",
"The element type.",
"The monoid type."
)]
#[document_parameters("The function to apply with index.", "The Identity value.")]
#[document_returns("The monoid result.")]
#[document_examples]
fn 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, {
func((), fa.0)
}
}
impl TraversableWithIndex for IdentityBrand {
#[document_signature]
#[document_type_parameters(
"The lifetime.",
"The element type.",
"The output type.",
"The applicative brand."
)]
#[document_parameters("The function to apply with index.", "The Identity value.")]
#[document_returns("The result in the applicative context.")]
#[document_examples]
fn traverse_with_index<'a, A: 'a, B: 'a + Clone, M: Applicative>(
func: 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, {
M::map::<B, Identity<B>>(Identity, func((), ta.0))
}
}
impl RefFunctorWithIndex for IdentityBrand {
#[document_signature]
#[document_type_parameters("The lifetime.", "The input type.", "The output type.")]
#[document_parameters("The function to apply with index.", "The Identity value.")]
#[document_returns("The transformed Identity value.")]
#[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>) {
Identity(func((), &fa.0))
}
}
impl RefFoldableWithIndex for IdentityBrand {
#[document_signature]
#[document_type_parameters(
"The lifetime.",
"The brand of the cloneable function.",
"The element type.",
"The monoid type."
)]
#[document_parameters("The function to apply with index.", "The Identity value.")]
#[document_returns("The monoid result.")]
#[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, {
func((), &fa.0)
}
}
impl RefTraversableWithIndex for IdentityBrand {
#[document_signature]
#[document_type_parameters(
"The lifetime.",
"The element type.",
"The output type.",
"The applicative brand."
)]
#[document_parameters("The function to apply with index.", "The Identity value.")]
#[document_returns("The result in the applicative context.")]
#[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, {
M::map(Identity, f((), &ta.0))
}
}
impl RefPointed for IdentityBrand {
#[document_signature]
#[document_type_parameters("The lifetime.", "The value type.")]
#[document_parameters("The reference to wrap.")]
#[document_returns("An Identity 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>) {
Identity(a.clone())
}
}
impl RefLift for IdentityBrand {
#[document_signature]
#[document_type_parameters("The lifetime.", "First input.", "Second input.", "Output.")]
#[document_parameters(
"The binary function.",
"The first Identity.",
"The second Identity."
)]
#[document_returns("The combined Identity.")]
#[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>) {
Identity(func(&fa.0, &fb.0))
}
}
impl RefSemiapplicative for IdentityBrand {
#[document_signature]
#[document_type_parameters(
"The lifetime.",
"The function brand.",
"The input type.",
"The output type."
)]
#[document_parameters(
"The Identity containing the function.",
"The Identity containing the value."
)]
#[document_returns("The Identity containing the 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>) {
Identity((*ff.0)(&fa.0))
}
}
impl RefSemimonad for IdentityBrand {
#[document_signature]
#[document_type_parameters("The lifetime.", "The input type.", "The output type.")]
#[document_parameters("The input Identity.", "The function to apply by reference.")]
#[document_returns("The resulting Identity.")]
#[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>) {
f(&fa.0)
}
}
}
pub use inner::*;
#[cfg(test)]
mod tests {
use {
super::inner::Identity,
crate::{
brands::{
IdentityBrand,
OptionBrand,
RcFnBrand,
},
classes::*,
functions::*,
},
quickcheck_macros::quickcheck,
};
#[quickcheck]
fn functor_identity(x: i32) -> bool {
let x = Identity(x);
explicit::map::<IdentityBrand, _, _, _, _>(identity, x) == x
}
#[quickcheck]
fn functor_composition(x: i32) -> bool {
let x = Identity(x);
let f = |x: i32| x.wrapping_add(1);
let g = |x: i32| x.wrapping_mul(2);
explicit::map::<IdentityBrand, _, _, _, _>(compose(f, g), x)
== explicit::map::<IdentityBrand, _, _, _, _>(
f,
explicit::map::<IdentityBrand, _, _, _, _>(g, x),
)
}
#[quickcheck]
fn applicative_identity(v: i32) -> bool {
let v = Identity(v);
apply(pure::<IdentityBrand, _>(<RcFnBrand as LiftFn>::new(identity)), v) == v
}
#[quickcheck]
fn applicative_homomorphism(x: i32) -> bool {
let f = |x: i32| x.wrapping_mul(2);
apply(pure::<IdentityBrand, _>(<RcFnBrand as LiftFn>::new(f)), pure::<IdentityBrand, _>(x))
== pure::<IdentityBrand, _>(f(x))
}
#[quickcheck]
fn applicative_composition(
w: i32,
u_val: i32,
v_val: i32,
) -> bool {
let w = Identity(w);
let v_fn = move |x: i32| x.wrapping_mul(v_val);
let u_fn = move |x: i32| x.wrapping_add(u_val);
let v = pure::<IdentityBrand, _>(<RcFnBrand as LiftFn>::new(v_fn));
let u = pure::<IdentityBrand, _>(<RcFnBrand as LiftFn>::new(u_fn));
let vw = apply(v.clone(), w);
let rhs = apply(u.clone(), vw);
let composed = move |x| u_fn(v_fn(x));
let uv = pure::<IdentityBrand, _>(<RcFnBrand as LiftFn>::new(composed));
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::<IdentityBrand, _>(<RcFnBrand as LiftFn>::new(f));
let lhs = apply(u.clone(), pure::<IdentityBrand, _>(y));
let rhs_fn = <RcFnBrand as LiftFn>::new(move |f: std::rc::Rc<dyn Fn(i32) -> i32>| f(y));
let rhs = apply(pure::<IdentityBrand, _>(rhs_fn), u);
lhs == rhs
}
#[quickcheck]
fn monad_left_identity(a: i32) -> bool {
let f = |x: i32| Identity(x.wrapping_mul(2));
explicit::bind::<IdentityBrand, _, _, _, _>(pure::<IdentityBrand, _>(a), f) == f(a)
}
#[quickcheck]
fn monad_right_identity(m: i32) -> bool {
let m = Identity(m);
explicit::bind::<IdentityBrand, _, _, _, _>(m, pure::<IdentityBrand, _>) == m
}
#[quickcheck]
fn monad_associativity(m: i32) -> bool {
let m = Identity(m);
let f = |x: i32| Identity(x.wrapping_mul(2));
let g = |x: i32| Identity(x.wrapping_add(1));
explicit::bind::<IdentityBrand, _, _, _, _>(
explicit::bind::<IdentityBrand, _, _, _, _>(m, f),
g,
) == explicit::bind::<IdentityBrand, _, _, _, _>(m, |x| {
explicit::bind::<IdentityBrand, _, _, _, _>(f(x), g)
})
}
#[test]
fn map_test() {
assert_eq!(
explicit::map::<IdentityBrand, _, _, _, _>(|x: i32| x + 1, Identity(1)),
Identity(2)
);
}
#[test]
fn bind_test() {
assert_eq!(
explicit::bind::<IdentityBrand, _, _, _, _>(Identity(1), |x| Identity(x + 1)),
Identity(2)
);
}
#[test]
fn fold_right_test() {
assert_eq!(
crate::functions::explicit::fold_right::<RcFnBrand, IdentityBrand, _, _, _, _>(
|x: i32, acc| x + acc,
0,
Identity(1)
),
1
);
}
#[test]
fn fold_left_test() {
assert_eq!(
crate::functions::explicit::fold_left::<RcFnBrand, IdentityBrand, _, _, _, _>(
|acc, x: i32| acc + x,
0,
Identity(1)
),
1
);
}
#[test]
fn traverse_test() {
assert_eq!(
crate::classes::traversable::traverse::<IdentityBrand, _, _, OptionBrand>(
|x: i32| Some(x + 1),
Identity(1)
),
Some(Identity(2))
);
}
#[quickcheck]
fn monad_rec_identity(x: i32) -> bool {
use {
crate::classes::monad_rec::tail_rec_m,
core::ops::ControlFlow,
};
tail_rec_m::<IdentityBrand, _, _>(|a| Identity(ControlFlow::Break(a)), x) == Identity(x)
}
#[test]
fn monad_rec_sum_range() {
use {
crate::classes::monad_rec::tail_rec_m,
core::ops::ControlFlow,
};
let result = tail_rec_m::<IdentityBrand, _, _>(
|(n, acc)| {
if n == 0 {
Identity(ControlFlow::Break(acc))
} else {
Identity(ControlFlow::Continue((n - 1, acc + n)))
}
},
(100i64, 0i64),
);
assert_eq!(result, Identity(5050));
}
#[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::<IdentityBrand, _, _>(
|acc| {
if acc < iterations {
Identity(ControlFlow::Continue(acc + 1))
} else {
Identity(ControlFlow::Break(acc))
}
},
0i64,
);
assert_eq!(result, Identity(iterations));
}
#[quickcheck]
fn extract_pure(x: i32) -> bool {
use crate::classes::extract::extract;
extract::<IdentityBrand, _>(pure::<IdentityBrand, _>(x)) == x
}
#[quickcheck]
fn comonad_left_identity(x: i32) -> bool {
use crate::classes::{
extend::extend,
extract::extract,
};
let f = |w: Identity<i32>| w.0.wrapping_mul(3);
let wa = Identity(x);
extract::<IdentityBrand, _>(extend::<IdentityBrand, _, _>(f, wa)) == f(wa)
}
#[quickcheck]
fn comonad_right_identity(x: i32) -> bool {
use crate::classes::{
extend::extend,
extract::extract,
};
extend::<IdentityBrand, _, _>(extract::<IdentityBrand, _>, Identity(x)) == Identity(x)
}
#[quickcheck]
fn extend_associativity(x: i32) -> bool {
use crate::classes::extend::extend;
let g = |w: Identity<i32>| w.0.wrapping_mul(2);
let f = |w: Identity<i32>| w.0.wrapping_add(1);
let wa = Identity(x);
let lhs = extend::<IdentityBrand, _, _>(f, extend::<IdentityBrand, _, _>(g, wa));
let rhs = extend::<IdentityBrand, _, _>(
|w: Identity<i32>| f(extend::<IdentityBrand, _, _>(g, w)),
wa,
);
lhs == rhs
}
#[quickcheck]
fn comonad_map_extract(x: i32) -> bool {
use crate::classes::extract::extract;
let f = |a: i32| a.wrapping_mul(5);
let wa = Identity(x);
extract::<IdentityBrand, _>(explicit::map::<IdentityBrand, _, _, _, _>(f, wa))
== f(extract::<IdentityBrand, _>(wa))
}
#[test]
fn extract_test() {
use crate::classes::extract::extract;
assert_eq!(extract::<IdentityBrand, _>(Identity(42)), 42);
}
#[test]
fn extend_test() {
use crate::classes::extend::extend;
let result = extend::<IdentityBrand, _, _>(|w: Identity<i32>| w.0 * 2, Identity(21));
assert_eq!(result, Identity(42));
}
#[quickcheck]
fn ref_functor_identity(v: i32) -> bool {
use crate::classes::ref_functor::RefFunctor;
IdentityBrand::ref_map(|x: &i32| *x, &Identity(v)) == Identity(v)
}
#[quickcheck]
fn ref_functor_composition(v: i32) -> bool {
use crate::classes::ref_functor::RefFunctor;
let f = |x: &i32| x.wrapping_add(1);
let g = |x: &i32| x.wrapping_mul(2);
IdentityBrand::ref_map(|x: &i32| f(&g(x)), &Identity(v))
== IdentityBrand::ref_map(f, &IdentityBrand::ref_map(g, &Identity(v)))
}
#[quickcheck]
fn ref_semimonad_left_identity(x: i32) -> bool {
use crate::classes::ref_semimonad::RefSemimonad;
IdentityBrand::ref_bind(&Identity(x), |a: &i32| Identity(*a)) == Identity(x)
}
}