use crate::prelude::*;
pub trait MonadOnce<M, A>: Monad<M, A>
where Self: Applicative<M, A>,
M: HKT1<T<A> = Self>
{
fn bind1<B, AMB>(self, f: AMB) -> M::T<B>
where AMB: F1Once<A, Ret = M::T<B>>;
fn discard<AMB, B>(self, f: AMB) -> M::T<A>
where Self: Sized,
B: Discard,
AMB: for<'a> F1Once<&'a A, Ret = M::T<B>>,
M::T<B>: MonadOnce<M, B>
{
self.bind1::<A, _>(|a| f.call1(&a).bind1::<A, _>(|_| M::T::<A>::pure(a)))
}
fn discard_mut<AMB, B>(self, f: AMB) -> M::T<A>
where Self: Sized,
B: Discard,
AMB: for<'a> F1Once<&'a mut A, Ret = M::T<B>>,
M::T<B>: MonadOnce<M, B>
{
self.bind1::<A, _>(|mut a| f.call1(&mut a).bind1::<A, _>(|_| M::T::<A>::pure(a)))
}
}
pub trait Monad<M, A>
where Self: Applicative<M, A>,
M: HKT1<T<A> = Self>
{
fn bind<B, AMB>(self, f: AMB) -> M::T<B>
where AMB: F1<A, Ret = M::T<B>>;
fn flatten<AA>(self) -> M::T<AA>
where Self: Sized,
M: HKT1<T<AA> = A> + HKT1<T<<M as HKT1>::T<AA>> = Self>
{
self.bind::<AA, _>(|s| s)
}
}
pub trait MonadSurrogate<M, A>
where Self: Equiv<To = M::T<A>> + ApplicativeSurrogate<M, A>,
M: HKT1
{
type BindOutput<B, AMB>;
fn bind_<B, AMB>(self, f: AMB) -> Self::BindOutput<B, AMB>
where AMB: F1<A, Ret = M::T<B>>,
Self::BindOutput<B, AMB>: Equiv<To = M::T<B>>;
}