radn-rs/src/func/instances/composition.rs

152 lines
4.6 KiB
Rust

use crate::func::*;
pub struct CompositionInstance<U, V>(U, V);
impl<'a, U: WeakFunctorA<'a>, V: WeakFunctorA<'a>> WeakFunctorA<'a> for CompositionInstance<U, V> {
type Fa<A: 'a> = U::Fa<V::Fa<A>>;
}
impl<'a, U: Functor<'a>, V: Functor<'a>> Functor<'a> for CompositionInstance<U, V> {
fn fmap<A: 'a, B: 'a>(f: impl 'a + FnOnce(A) -> B, fa: Self::Fa<A>) -> Self::Fa<B> {
U::fmap(|ua| V::fmap(f, ua), fa)
}
fn replace<A: 'a, B: 'a>(fa: Self::Fa<A>, b: B) -> Self::Fa<B> {
U::fmap(|ua| V::replace(ua, b), fa)
}
fn void<A: 'a>(fa: Self::Fa<A>) -> Self::Fa<()> {
U::fmap(|ua| V::void(ua), fa)
}
}
impl<'a, U: Pure<'a>, V: Pure<'a>> Pure<'a> for CompositionInstance<U, V> {
fn pure<A: 'a>(a: A) -> Self::Fa<A> {
U::pure(V::pure(a))
}
}
impl<'a, U: ApplicativeLA2<'a>, V: ApplicativeSeq<'a>> ApplicativeSeq<'a>
for CompositionInstance<U, V>
{
fn seq<A: 'a, B: 'a>(ff: Self::Fa<impl 'a + FnOnce(A) -> B>, fa: Self::Fa<A>) -> Self::Fa<B> {
U::la2(|uf, ua| V::seq(uf, ua), ff, fa)
}
}
impl<'a, U: ApplicativeLA2<'a>, V: ApplicativeLA2<'a>> ApplicativeLA2<'a>
for CompositionInstance<U, V>
{
fn la2<A: 'a, B: 'a, C: 'a>(
f: impl 'a + FnOnce(A, B) -> C,
fa: Self::Fa<A>,
fb: Self::Fa<B>,
) -> Self::Fa<C> {
U::la2(|ua, ub| V::la2(f, ua, ub), fa, fb)
}
}
impl<'a, U: ApplicativeTuple<'a>, V: ApplicativeTuple<'a>> ApplicativeTuple<'a>
for CompositionInstance<U, V>
{
fn tuple<A: 'a, B: 'a>(fab: (Self::Fa<A>, Self::Fa<B>)) -> Self::Fa<(A, B)> {
U::fmap(V::tuple, U::tuple(fab))
}
}
impl<'a, U: ApplicativeSelect<'a>, V: Functor<'a>> ApplicativeSelect<'a>
for CompositionInstance<U, V>
{
fn select<A: 'a, B: 'a>(fa: Self::Fa<A>, fb: Self::Fa<B>) -> SelectedWrapped<'a, A, B, Self> {
U::fmap(
|selected| match selected {
Selected::A(ua, fb) => V::fmap(|a| Selected::A(a, fb), ua),
Selected::B(fa, ub) => V::fmap(|b| Selected::B(fa, b), ub),
},
U::select(fa, fb),
)
}
}
impl<'a, U: Applicative<'a>, V: Applicative<'a>> Applicative<'a> for CompositionInstance<U, V> {
fn discard_first<A: 'a, B: 'a>(fa: Self::Fa<A>, fb: Self::Fa<B>) -> Self::Fa<B> {
U::la2(|ua, ub| V::discard_first(ua, ub), fa, fb)
}
fn discard_second<A: 'a, B: 'a>(fa: Self::Fa<A>, fb: Self::Fa<B>) -> Self::Fa<A> {
U::la2(|ua, ub| V::discard_second(ua, ub), fa, fb)
}
}
impl<'a, U: Monad<'a>, V: Monad<'a> + LocalFunctor<'a>> Monad<'a> for CompositionInstance<U, V> {
fn bind<A: 'a, B: 'a>(fa: Self::Fa<A>, f: impl 'a + FnOnce(A) -> Self::Fa<B>) -> Self::Fa<B> {
U::bind(fa, |ua| U::fmap(V::join, V::stuff::<_, U>(V::fmap(f, ua))))
}
fn iterate<B: 'a>(f: impl Iterative<'a, T = Self, B = B>) -> Self::Fa<B> {
U::iterate(ComposedIterative(f))
}
fn join<A: 'a>(ffa: Self::Fa<Self::Fa<A>>) -> Self::Fa<A> {
U::join(U::fmap(|ufa| U::fmap(V::join, V::stuff::<_, U>(ufa)), ffa))
}
}
struct ComposedIterative<F>(F);
impl<
'a,
U: Monad<'a>,
V: Monad<'a> + LocalFunctor<'a>,
F: Iterative<'a, T = CompositionInstance<U, V>>,
> Iterative<'a> for ComposedIterative<F>
{
type B = Wrap<'a, F::B, V>;
type T = U;
fn next(self) -> IterativeWrapped<'a, Self> {
let fstate = self.0.next();
U::fmap(
|ustate| match V::unstuff(ustate) {
ControlFlow::Continue(next_f) => ControlFlow::Continue(Self(next_f)),
ControlFlow::Break(b) => ControlFlow::Break(b),
},
fstate,
)
}
}
impl<'a, E: 'a, U: Monad<'a>, V: Fail<'a, E> + LocalFunctor<'a>> Fail<'a, E>
for CompositionInstance<U, V>
{
fn fail<A: 'a>(e: E) -> Self::Fa<A> {
U::pure(V::fail(e))
}
}
impl<'a, U: LocalFunctor<'a> + Functor<'a>, V: LocalFunctor<'a>> LocalFunctor<'a>
for CompositionInstance<U, V>
{
fn unstuff<A: 'a, B: 'a>(state: Self::Fa<ControlFlow<B, A>>) -> ControlFlow<Self::Fa<B>, A> {
U::unstuff(U::fmap(V::unstuff, state))
}
fn stuff<A: 'a, T: Pure<'a>>(fa: Self::Fa<T::Fa<A>>) -> T::Fa<Self::Fa<A>> {
U::stuff::<_, T>(U::fmap(V::stuff::<_, T>, fa))
}
}
impl<'a, U: SharedFunctorA<'a> + Functor<'a>, V: SharedFunctorA<'a>> SharedFunctorA<'a>
for CompositionInstance<U, V>
{
type SharedA<A: 'a + Clone> = U::SharedA<V::SharedA<A>>;
fn share<A: 'a + Clone>(fa: Self::Fa<A>) -> Self::SharedA<A> {
U::share(U::fmap(V::share, fa))
}
fn unshare<A: 'a + Clone>(sa: Self::SharedA<A>) -> Self::Fa<A> {
U::fmap(V::unshare, U::unshare(sa))
}
}