use rust2fun_macros::ap_n;
use crate::and_then::AndThen;
use crate::functor::Functor;
use crate::higher::Higher;
use crate::semigroupal::Semigroupal;
pub trait ApN<Z>: AndThen<Z> {
#[inline]
fn ap2<A, B>(self, fa: Self::Target<A>, fb: Self::Target<B>) -> Self::Target<Z>
where
Self::Param: FnMut(A, B) -> Z,
Self::Target<A>: Semigroupal<B, Target<B> = Self::Target<B>>
+ Higher<Target<(A, B)> = Self::Target<(A, B)>>,
Self::Target<(A, B)>: Functor<Z, Target<Z> = Self::Target<Z>> + Clone,
Self: Sized,
{
let product = fa.product(fb);
self.and_then(|mut f| product.clone().map(move |(a, b)| f(a, b)))
}
#[inline]
fn ap3<A, B, C>(
self,
fa: Self::Target<A>,
fb: Self::Target<B>,
fc: Self::Target<C>,
) -> Self::Target<Z>
where
Self::Param: FnMut(A, B, C) -> Z,
Self::Target<A>: Semigroupal<B, Target<B> = Self::Target<B>>
+ Higher<Target<(A, B)> = Self::Target<(A, B)>>,
Self::Target<(A, B)>: Semigroupal<C, Target<C> = Self::Target<C>>
+ Higher<Target<((A, B), C)> = Self::Target<((A, B), C)>>,
Self::Target<((A, B), C)>: Functor<Z, Target<Z> = Self::Target<Z>> + Clone,
Self: Sized,
{
let product = fa.product(fb).product(fc);
self.and_then(|mut f| product.clone().map(move |((a, b), c)| f(a, b, c)))
}
ap_n!(4);
ap_n!(5);
ap_n!(6);
ap_n!(7);
ap_n!(8);
ap_n!(9);
ap_n!(10);
ap_n!(11);
ap_n!(12);
}
impl<Z, T: AndThen<Z>> ApN<Z> for T {}