func::fail
This commit is contained in:
parent
625ccbdc31
commit
25ede0db44
87
src/func.rs
87
src/func.rs
@ -12,6 +12,7 @@ pub mod context;
|
||||
mod controlflow;
|
||||
pub mod derivations;
|
||||
mod extensions;
|
||||
mod fail;
|
||||
pub mod instances;
|
||||
pub mod shared;
|
||||
#[cfg(test)]
|
||||
@ -27,6 +28,7 @@ pub use self::applicative_select::{
|
||||
use self::controlflow::{BindableMut, ControlFlowInstance};
|
||||
pub use self::controlflow::{Iterative, IterativeWrapped};
|
||||
pub use self::extensions::{MonadExt, MonadFailAnyExt};
|
||||
pub use self::fail::{Fail, MonadFail, MonadFailAny, WrapE};
|
||||
#[cfg(doc)]
|
||||
use self::instances::stackless::StacklessInstance;
|
||||
|
||||
@ -139,19 +141,6 @@ pub trait Monad<'a>: Applicative<'a> {
|
||||
|
||||
impl<'a, T: Monad<'a>> MonadExt<'a> for T {}
|
||||
|
||||
/// Part of [`MonadFail`] responsible for Haskell's `fail`.
|
||||
pub trait Fail<'a, E: 'a>: WeakFunctor<'a> {
|
||||
/// Equivalent of Haskell's `fail`.
|
||||
fn fail<A: 'a>(e: E) -> Self::F<A>;
|
||||
}
|
||||
|
||||
/// Equivalent of Haskell's `MonadFail`. Auto-implemented for all [`Fail`]`+`[`Monad`].
|
||||
///
|
||||
/// <https://hackage.haskell.org/package/base-4.18.0.0/docs/Control-Monad.html>
|
||||
pub trait MonadFail<'a, E: 'a>: Monad<'a> + Fail<'a, E> {}
|
||||
|
||||
impl<'a, E: 'a, T: Monad<'a> + Fail<'a, E>> MonadFail<'a, E> for T {}
|
||||
|
||||
/// Represents wrapped results which are instantly available.
|
||||
pub trait LocalFunctor<'a>: WeakFunctor<'a> {
|
||||
/// Extract iteration state, if successful.
|
||||
@ -162,75 +151,3 @@ pub trait LocalFunctor<'a>: WeakFunctor<'a> {
|
||||
/// Stuff wrapped result into another functor.
|
||||
fn stuff<A: 'a, T: Pure<'a>>(fa: Self::F<T::F<A>>) -> T::F<Self::F<A>>;
|
||||
}
|
||||
|
||||
/// Represents a (collection of) [Monad]\(s) that can hold any type of error.
|
||||
pub trait MonadFailAny<'a>: 'a {
|
||||
/// [`MonadFail`] for a specific error type.
|
||||
type W<E>: MonadFail<'a, E>
|
||||
where
|
||||
E: 'a;
|
||||
|
||||
/// Associated infallible [`Monad`].
|
||||
type T: Monad<'a>;
|
||||
|
||||
fn unstuff<A: 'a, E: 'a>(wa: WrapE<'a, A, E, Self>) -> Wrap<'a, Result<A, E>, Self::T>;
|
||||
|
||||
fn stuff<A: 'a, E: 'a>(fa: Wrap<'a, Result<A, E>, Self::T>) -> WrapE<'a, A, E, Self>;
|
||||
|
||||
/// Equivalent of [`Result::map_err`].
|
||||
fn map_err<A: 'a, E0: 'a, E1: 'a>(
|
||||
wa: WrapE<'a, A, E0, Self>,
|
||||
f: impl 'a + FnOnce(E0) -> E1,
|
||||
) -> WrapE<'a, A, E1, Self> {
|
||||
Self::bind_err(wa, |e0| Self::fail(f(e0)))
|
||||
}
|
||||
|
||||
/// Equivalent of `catch`/`except`. To inject errors on success, see [`MonadFailAny::bind`].
|
||||
fn bind_err<A: 'a, E0: 'a, E1: 'a>(
|
||||
wa: WrapE<'a, A, E0, Self>,
|
||||
f: impl 'a + FnOnce(E0) -> WrapE<'a, A, E1, Self>,
|
||||
) -> WrapE<'a, A, E1, Self> {
|
||||
Self::bind(wa, |result| match result {
|
||||
Ok(a) => Self::pure(a),
|
||||
Err(e0) => f(e0),
|
||||
})
|
||||
}
|
||||
|
||||
/// Bind the result, an equivalent of `catch`/`except` with ability to "raise" extra errors
|
||||
/// on success too, unlike [`MonadFailAny::bind_err`].
|
||||
///
|
||||
/// Note: Reasonably it is expected to lack fail semantics for the underlying result.
|
||||
/// Therefore the default implementation descends into the non-fail monad [`MonadFailAny::T`].
|
||||
fn bind<A: 'a, B: 'a, E0: 'a, E1: 'a>(
|
||||
wa: WrapE<'a, A, E0, Self>,
|
||||
f: impl 'a + FnOnce(Result<A, E0>) -> WrapE<'a, B, E1, Self>,
|
||||
) -> WrapE<'a, B, E1, Self> {
|
||||
Self::stuff(<Self::T as Monad>::bind(Self::unstuff(wa), |result| {
|
||||
Self::unstuff(f(result))
|
||||
}))
|
||||
}
|
||||
|
||||
/// Equivalent of [`Monad::join`], flattening the errors.
|
||||
///
|
||||
/// Note: default implementation doesn't depend on [`Monad::join`].
|
||||
fn join<A: 'a, E0: 'a, E1: 'a>(
|
||||
wwa: WrapE<'a, WrapE<'a, A, E0, Self>, E1, Self>,
|
||||
) -> WrapE<'a, A, Result<E0, E1>, Self> {
|
||||
Self::bind(wwa, |result| match result {
|
||||
Ok(wa) => Self::map_err(wa, Ok),
|
||||
Err(e1) => Self::fail(Err(e1)),
|
||||
})
|
||||
}
|
||||
|
||||
/// Lift the error.
|
||||
fn rotate_out<A: 'a, E0: 'a, E1: 'a>(
|
||||
wa: WrapE<'a, Result<A, E1>, E0, Self>,
|
||||
) -> WrapE<'a, A, Result<E1, E0>, Self> {
|
||||
<Self::W<Result<E1, E0>> as Monad>::bind(Self::map_err(wa, Err), |fa| match fa {
|
||||
Ok(a) => Self::pure(a),
|
||||
Err(e) => Self::fail(Ok(e)),
|
||||
})
|
||||
}
|
||||
}
|
||||
|
||||
pub type WrapE<'a, A, E, Fallible> = Wrap<'a, A, <Fallible as MonadFailAny<'a>>::W<E>>;
|
||||
|
86
src/func/fail.rs
Normal file
86
src/func/fail.rs
Normal file
@ -0,0 +1,86 @@
|
||||
use super::*;
|
||||
|
||||
/// Part of [`MonadFail`] responsible for Haskell's `fail`.
|
||||
pub trait Fail<'a, E: 'a>: WeakFunctor<'a> {
|
||||
/// Equivalent of Haskell's `fail`.
|
||||
fn fail<A: 'a>(e: E) -> Self::F<A>;
|
||||
}
|
||||
|
||||
/// Equivalent of Haskell's `MonadFail`. Auto-implemented for all [`Fail`]`+`[`Monad`].
|
||||
///
|
||||
/// <https://hackage.haskell.org/package/base-4.18.0.0/docs/Control-Monad.html>
|
||||
pub trait MonadFail<'a, E: 'a>: Monad<'a> + Fail<'a, E> {}
|
||||
|
||||
impl<'a, E: 'a, T: Monad<'a> + Fail<'a, E>> MonadFail<'a, E> for T {}
|
||||
|
||||
/// Represents a (collection of) [Monad]\(s) that can hold any type of error.
|
||||
pub trait MonadFailAny<'a>: 'a {
|
||||
/// [`MonadFail`] for a specific error type.
|
||||
type W<E>: MonadFail<'a, E>
|
||||
where
|
||||
E: 'a;
|
||||
|
||||
/// Associated infallible [`Monad`].
|
||||
type T: Monad<'a>;
|
||||
|
||||
fn unstuff<A: 'a, E: 'a>(wa: WrapE<'a, A, E, Self>) -> Wrap<'a, Result<A, E>, Self::T>;
|
||||
|
||||
fn stuff<A: 'a, E: 'a>(fa: Wrap<'a, Result<A, E>, Self::T>) -> WrapE<'a, A, E, Self>;
|
||||
|
||||
/// Equivalent of [`Result::map_err`].
|
||||
fn map_err<A: 'a, E0: 'a, E1: 'a>(
|
||||
wa: WrapE<'a, A, E0, Self>,
|
||||
f: impl 'a + FnOnce(E0) -> E1,
|
||||
) -> WrapE<'a, A, E1, Self> {
|
||||
Self::bind_err(wa, |e0| Self::fail(f(e0)))
|
||||
}
|
||||
|
||||
/// Equivalent of `catch`/`except`. To inject errors on success, see [`MonadFailAny::bind`].
|
||||
fn bind_err<A: 'a, E0: 'a, E1: 'a>(
|
||||
wa: WrapE<'a, A, E0, Self>,
|
||||
f: impl 'a + FnOnce(E0) -> WrapE<'a, A, E1, Self>,
|
||||
) -> WrapE<'a, A, E1, Self> {
|
||||
Self::bind(wa, |result| match result {
|
||||
Ok(a) => Self::pure(a),
|
||||
Err(e0) => f(e0),
|
||||
})
|
||||
}
|
||||
|
||||
/// Bind the result, an equivalent of `catch`/`except` with ability to "raise" extra errors
|
||||
/// on success too, unlike [`MonadFailAny::bind_err`].
|
||||
///
|
||||
/// Note: Reasonably it is expected to lack fail semantics for the underlying result.
|
||||
/// Therefore the default implementation descends into the non-fail monad [`MonadFailAny::T`].
|
||||
fn bind<A: 'a, B: 'a, E0: 'a, E1: 'a>(
|
||||
wa: WrapE<'a, A, E0, Self>,
|
||||
f: impl 'a + FnOnce(Result<A, E0>) -> WrapE<'a, B, E1, Self>,
|
||||
) -> WrapE<'a, B, E1, Self> {
|
||||
Self::stuff(<Self::T as Monad>::bind(Self::unstuff(wa), |result| {
|
||||
Self::unstuff(f(result))
|
||||
}))
|
||||
}
|
||||
|
||||
/// Equivalent of [`Monad::join`], flattening the errors.
|
||||
///
|
||||
/// Note: default implementation doesn't depend on [`Monad::join`].
|
||||
fn join<A: 'a, E0: 'a, E1: 'a>(
|
||||
wwa: WrapE<'a, WrapE<'a, A, E0, Self>, E1, Self>,
|
||||
) -> WrapE<'a, A, Result<E0, E1>, Self> {
|
||||
Self::bind(wwa, |result| match result {
|
||||
Ok(wa) => Self::map_err(wa, Ok),
|
||||
Err(e1) => Self::fail(Err(e1)),
|
||||
})
|
||||
}
|
||||
|
||||
/// Lift the error.
|
||||
fn rotate_out<A: 'a, E0: 'a, E1: 'a>(
|
||||
wa: WrapE<'a, Result<A, E1>, E0, Self>,
|
||||
) -> WrapE<'a, A, Result<E1, E0>, Self> {
|
||||
<Self::W<Result<E1, E0>> as Monad>::bind(Self::map_err(wa, Err), |fa| match fa {
|
||||
Ok(a) => Self::pure(a),
|
||||
Err(e) => Self::fail(Ok(e)),
|
||||
})
|
||||
}
|
||||
}
|
||||
|
||||
pub type WrapE<'a, A, E, Fallible> = Wrap<'a, A, <Fallible as MonadFailAny<'a>>::W<E>>;
|
Loading…
Reference in New Issue
Block a user