//! [Functor]s derived on compositions of other [Functor]s. //! //! For changing behaviour of existing [instances], see [`overload`]. //! //! For [`future`]-[`result`] composition, see [`tryfuture`]. //! //! [`overload`]: super::overload //! [`future`]: super::future //! [`result`]: super::result //! [`tryfuture`]: super::tryfuture use crate::func::class_prelude::*; pub struct CompositionInstance(U, V); impl<'a, U: WeakFunctor<'a>, V: WeakFunctor<'a>> WeakFunctor<'a> for CompositionInstance { type F = U::F>; } impl<'a, U: Functor<'a>, V: Functor<'a>> Functor<'a> for CompositionInstance { fn fmap(fa: Self::F, f: impl 'a + FnOnce(A) -> B) -> Self::F { U::fmap(fa, |ua| V::fmap(ua, f)) } fn replace(fa: Self::F, b: B) -> Self::F { U::fmap(fa, |ua| V::replace(ua, b)) } fn void(fa: Self::F) -> Self::F<()> { U::fmap(fa, |ua| V::void(ua)) } } impl<'a, U: Pure<'a>, V: Pure<'a>> Pure<'a> for CompositionInstance { fn pure(a: A) -> Self::F { U::pure(V::pure(a)) } } /// Note: depends on the outer instance being [`ApplicativeLA2`] not [`ApplicativeSeq`]. impl<'a, U: ApplicativeLA2<'a>, V: ApplicativeSeq<'a>> ApplicativeSeq<'a> for CompositionInstance { fn seq(ff: Self::F B>, fa: Self::F) -> Self::F { U::la2(ff, fa, V::seq) } } impl<'a, U: ApplicativeLA2<'a>, V: ApplicativeLA2<'a>> ApplicativeLA2<'a> for CompositionInstance { fn la2( fa: Self::F, fb: Self::F, f: impl 'a + FnOnce(A, B) -> C, ) -> Self::F { U::la2(fa, fb, |ua, ub| V::la2(ua, ub, f)) } } impl<'a, U: ApplicativeTuple<'a>, V: ApplicativeTuple<'a>> ApplicativeTuple<'a> for CompositionInstance { fn tuple(fab: (Self::F, Self::F)) -> Self::F<(A, B)> { U::fmap(U::tuple(fab), V::tuple) } } /// Note: depends on the inner instance being [`Functor`] not [`ApplicativeSelect`]. impl<'a, U: ApplicativeSelect<'a>, V: Functor<'a>> ApplicativeSelect<'a> for CompositionInstance { fn select(fa: Self::F, fb: Self::F) -> SelectedWrapped<'a, A, B, Self> { U::fmap(U::select(fa, fb), |selected| match selected { Selected::A(ua, fb) => V::fmap(ua, |a| Selected::A(a, fb)), Selected::B(fa, ub) => V::fmap(ub, |b| Selected::B(fa, b)), }) } } impl<'a, U: Applicative<'a>, V: Applicative<'a>> Applicative<'a> for CompositionInstance { fn discard_first(fa: Self::F, fb: Self::F) -> Self::F { U::la2(fa, fb, V::discard_first) } fn discard_second(fa: Self::F, fb: Self::F) -> Self::F { U::la2(fa, fb, V::discard_second) } } impl<'a, U: Monad<'a>, V: Monad<'a> + LocalFunctor<'a>> Monad<'a> for CompositionInstance { fn bind(fa: Self::F, f: impl 'a + FnOnce(A) -> Self::F) -> Self::F { U::bind(fa, |ua| U::fmap(V::stuff::<_, U>(V::fmap(ua, f)), V::join)) } fn iterate(f: impl Iterative<'a, T = Self, B = B>) -> Self::F { U::iterate(ComposedIterative(f)) } /// Basis for how composition can be a [Monad]. /// /// ```text /// U V U V A /// U U V V A /// U V A /// ``` fn join(ffa: Self::F>) -> Self::F { U::join(U::fmap(ffa, |ufa| U::fmap(V::stuff::<_, U>(ufa), V::join))) } } struct ComposedIterative(F); impl< 'a, U: Monad<'a>, V: Monad<'a> + LocalFunctor<'a>, F: Iterative<'a, T = CompositionInstance>, > Iterative<'a> for ComposedIterative { type B = Wrap<'a, F::B, V>; type T = U; fn next(self) -> IterativeWrapped<'a, Self> { let fstate = self.0.next(); U::fmap(fstate, |ustate| { ControlFlow::Continue(Self(V::unstuff(ustate)?)) }) } } /// Note: fails in the inner instance not outer. impl<'a, E: 'a, U: Monad<'a>, V: Fail<'a, E> + LocalFunctor<'a>> Fail<'a, E> for CompositionInstance { fn fail(e: E) -> Self::F { U::pure(V::fail(e)) } } impl<'a, U: LocalFunctor<'a> + Functor<'a>, V: LocalFunctor<'a>> LocalFunctor<'a> for CompositionInstance { fn unstuff(state: Self::F>) -> ControlFlow, A> { U::unstuff(U::fmap(state, V::unstuff)) } fn stuff>(fa: Self::F>) -> T::F> { U::stuff::<_, T>(U::fmap(fa, V::stuff::<_, T>)) } } impl<'a, U: SharedFunctor<'a> + Functor<'a>, V: SharedFunctor<'a>> SharedFunctor<'a> for CompositionInstance { type Shared = U::Shared>; fn share(fa: Self::F) -> Self::Shared { U::share(U::fmap(fa, V::share)) } fn unshare(sa: Self::Shared) -> Self::F { U::fmap(U::unshare(sa), V::unshare) } }