166 lines
5.0 KiB
Rust
166 lines
5.0 KiB
Rust
//! [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>(U, V);
|
|
|
|
impl<'a, U: WeakFunctor<'a>, V: WeakFunctor<'a>> WeakFunctor<'a> for CompositionInstance<U, V> {
|
|
type F<A: 'a> = U::F<V::F<A>>;
|
|
}
|
|
|
|
impl<'a, U: Functor<'a>, V: Functor<'a>> Functor<'a> for CompositionInstance<U, V> {
|
|
fn fmap<A: 'a, B: 'a>(fa: Self::F<A>, f: impl 'a + FnOnce(A) -> B) -> Self::F<B> {
|
|
U::fmap(fa, |ua| V::fmap(ua, f))
|
|
}
|
|
|
|
fn replace<A: 'a, B: 'a>(fa: Self::F<A>, b: B) -> Self::F<B> {
|
|
U::fmap(fa, |ua| V::replace(ua, b))
|
|
}
|
|
|
|
fn void<A: 'a>(fa: Self::F<A>) -> Self::F<()> {
|
|
U::fmap(fa, |ua| V::void(ua))
|
|
}
|
|
}
|
|
|
|
impl<'a, U: Pure<'a>, V: Pure<'a>> Pure<'a> for CompositionInstance<U, V> {
|
|
fn pure<A: 'a>(a: A) -> Self::F<A> {
|
|
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<U, V>
|
|
{
|
|
fn seq<A: 'a, B: 'a>(ff: Self::F<impl 'a + FnOnce(A) -> B>, fa: Self::F<A>) -> Self::F<B> {
|
|
U::la2(ff, fa, V::seq)
|
|
}
|
|
}
|
|
|
|
impl<'a, U: ApplicativeLA2<'a>, V: ApplicativeLA2<'a>> ApplicativeLA2<'a>
|
|
for CompositionInstance<U, V>
|
|
{
|
|
fn la2<A: 'a, B: 'a, C: 'a>(
|
|
fa: Self::F<A>,
|
|
fb: Self::F<B>,
|
|
f: impl 'a + FnOnce(A, B) -> C,
|
|
) -> Self::F<C> {
|
|
U::la2(fa, fb, |ua, ub| V::la2(ua, ub, f))
|
|
}
|
|
}
|
|
|
|
impl<'a, U: ApplicativeTuple<'a>, V: ApplicativeTuple<'a>> ApplicativeTuple<'a>
|
|
for CompositionInstance<U, V>
|
|
{
|
|
fn tuple<A: 'a, B: 'a>(fab: (Self::F<A>, Self::F<B>)) -> 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<U, V>
|
|
{
|
|
fn select<A: 'a, B: 'a>(fa: Self::F<A>, fb: Self::F<B>) -> 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<U, V> {
|
|
fn discard_first<A: 'a, B: 'a>(fa: Self::F<A>, fb: Self::F<B>) -> Self::F<B> {
|
|
U::la2(fa, fb, V::discard_first)
|
|
}
|
|
|
|
fn discard_second<A: 'a, B: 'a>(fa: Self::F<A>, fb: Self::F<B>) -> Self::F<A> {
|
|
U::la2(fa, fb, V::discard_second)
|
|
}
|
|
}
|
|
|
|
impl<'a, U: Monad<'a>, V: Monad<'a> + LocalFunctor<'a>> Monad<'a> for CompositionInstance<U, V> {
|
|
fn bind<A: 'a, B: 'a>(fa: Self::F<A>, f: impl 'a + FnOnce(A) -> Self::F<B>) -> Self::F<B> {
|
|
U::bind(fa, |ua| U::fmap(V::stuff::<_, U>(V::fmap(ua, f)), V::join))
|
|
}
|
|
|
|
fn iterate<B: 'a>(f: impl Iterative<'a, T = Self, B = B>) -> Self::F<B> {
|
|
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<A: 'a>(ffa: Self::F<Self::F<A>>) -> Self::F<A> {
|
|
U::join(U::fmap(ffa, |ufa| U::fmap(V::stuff::<_, U>(ufa), V::join)))
|
|
}
|
|
}
|
|
|
|
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(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<U, V>
|
|
{
|
|
fn fail<A: 'a>(e: E) -> Self::F<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::F<ControlFlow<B, A>>) -> ControlFlow<Self::F<B>, A> {
|
|
U::unstuff(U::fmap(state, V::unstuff))
|
|
}
|
|
|
|
fn stuff<A: 'a, T: Pure<'a>>(fa: Self::F<T::F<A>>) -> T::F<Self::F<A>> {
|
|
U::stuff::<_, T>(U::fmap(fa, V::stuff::<_, T>))
|
|
}
|
|
}
|
|
|
|
impl<'a, U: SharedFunctor<'a> + Functor<'a>, V: SharedFunctor<'a>> SharedFunctor<'a>
|
|
for CompositionInstance<U, V>
|
|
{
|
|
type Shared<A: 'a + Clone> = U::Shared<V::Shared<A>>;
|
|
|
|
fn share<A: 'a + Clone>(fa: Self::F<A>) -> Self::Shared<A> {
|
|
U::share(U::fmap(fa, V::share))
|
|
}
|
|
|
|
fn unshare<A: 'a + Clone>(sa: Self::Shared<A>) -> Self::F<A> {
|
|
U::fmap(U::unshare(sa), V::unshare)
|
|
}
|
|
}
|