83 lines
2.4 KiB
Rust
83 lines
2.4 KiB
Rust
use super::{fail::*, *};
|
|
|
|
pub type WrapC<'a, A, Ctx> = Wrap<'a, A, <Ctx as FunctorContext<'a>>::T>;
|
|
|
|
pub trait FunctorContext<'a>: 'a + Send {
|
|
type T: WeakFunctor<'a>;
|
|
}
|
|
|
|
pub trait MonadContext<'a>: FunctorContext<'a, T = Self::_Tm> {
|
|
type _Tm: Monad<'a>;
|
|
}
|
|
|
|
pub trait FunctorContextExt<'a>: FunctorContext<'a> {
|
|
fn fmap<A: 'a + Send, B: 'a + Send>(
|
|
fa: WrapC<'a, A, Self>,
|
|
f: impl 'a + Send + FnOnce(A) -> B,
|
|
) -> WrapC<'a, B, Self>
|
|
where
|
|
Self::T: Functor<'a>,
|
|
{
|
|
<Self::T as Functor>::fmap(fa, f)
|
|
}
|
|
|
|
fn pure<A: 'a + Send>(a: A) -> WrapC<'a, A, Self>
|
|
where
|
|
Self::T: Pure<'a>,
|
|
{
|
|
<Self::T as Pure>::pure(a)
|
|
}
|
|
|
|
fn bind<A: 'a + Send, B: 'a + Send>(
|
|
fa: WrapC<'a, A, Self>,
|
|
f: impl 'a + Send + FnOnce(A) -> WrapC<'a, B, Self>,
|
|
) -> WrapC<'a, B, Self>
|
|
where
|
|
Self::T: Monad<'a>,
|
|
{
|
|
<Self::T as Monad>::bind(fa, f)
|
|
}
|
|
|
|
fn fail<A: 'a + Send, E: 'a + Send>(e: E) -> WrapC<'a, A, Self>
|
|
where
|
|
Self::T: Fail<'a, E>,
|
|
{
|
|
<Self::T as Fail<_>>::fail(e)
|
|
}
|
|
}
|
|
|
|
impl<'a, Ctx: FunctorContext<'a>> FunctorContextExt<'a> for Ctx {}
|
|
|
|
pub trait FallibleCtx<'a>: FunctorContext<'a> {
|
|
/// Type to allow improved support for [`Result`] evaluation.
|
|
/// This is important for async applications stopping early.
|
|
type Fallible: MonadFailAny<'a, T = Self::T>;
|
|
}
|
|
|
|
/// Preferred monad for fallible uses.
|
|
pub type FallibleMonad<'a, Ctx, E> = <<Ctx as FallibleCtx<'a>>::Fallible as MonadFailAny<'a>>::W<E>;
|
|
|
|
/// Preferred [Wrap]ped [Result].
|
|
pub type FallibleWrapped<'a, Ctx, A, E> = Wrap<'a, A, FallibleMonad<'a, Ctx, E>>;
|
|
|
|
/// Extention trait for simpler conversion between [`FunctorContext::T`] and [`FallibleCtx::Fallible`].
|
|
///
|
|
/// this is the preferred way to switch between [WrapC] and [FallibleWrapped].
|
|
pub trait FallibleCtxExt<'a>: FallibleCtx<'a> {
|
|
/// Convert a fallible wrapped into a wrapped result.
|
|
fn unstuff<A: 'a + Send, E: 'a + Send>(
|
|
wa: FallibleWrapped<'a, Self, A, E>,
|
|
) -> WrapC<'a, Result<A, E>, Self> {
|
|
Self::Fallible::unstuff(wa)
|
|
}
|
|
|
|
/// Convert a wrapped result into a fallible wrapped.
|
|
fn stuff<A: 'a + Send, E: 'a + Send>(
|
|
fa: WrapC<'a, Result<A, E>, Self>,
|
|
) -> FallibleWrapped<'a, Self, A, E> {
|
|
Self::Fallible::stuff(fa)
|
|
}
|
|
}
|
|
|
|
impl<'a, Ctx: FallibleCtx<'a>> FallibleCtxExt<'a> for Ctx {}
|