From 25ede0db4404999fa3039e744ba6f2c73bce3e76 Mon Sep 17 00:00:00 2001 From: timofey Date: Sun, 18 Jun 2023 11:09:12 +0000 Subject: [PATCH] `func::fail` --- src/func.rs | 87 ++---------------------------------------------- src/func/fail.rs | 86 +++++++++++++++++++++++++++++++++++++++++++++++ 2 files changed, 88 insertions(+), 85 deletions(-) create mode 100644 src/func/fail.rs diff --git a/src/func.rs b/src/func.rs index 8b085d4..f386cf5 100644 --- a/src/func.rs +++ b/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(e: E) -> Self::F; -} - -/// Equivalent of Haskell's `MonadFail`. Auto-implemented for all [`Fail`]`+`[`Monad`]. -/// -/// -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>(fa: Self::F>) -> T::F>; } - -/// 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: MonadFail<'a, E> - where - E: 'a; - - /// Associated infallible [`Monad`]. - type T: Monad<'a>; - - fn unstuff(wa: WrapE<'a, A, E, Self>) -> Wrap<'a, Result, Self::T>; - - fn stuff(fa: Wrap<'a, Result, Self::T>) -> WrapE<'a, A, E, Self>; - - /// Equivalent of [`Result::map_err`]. - fn map_err( - 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( - 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( - wa: WrapE<'a, A, E0, Self>, - f: impl 'a + FnOnce(Result) -> WrapE<'a, B, E1, Self>, - ) -> WrapE<'a, B, E1, Self> { - Self::stuff(::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( - wwa: WrapE<'a, WrapE<'a, A, E0, Self>, E1, Self>, - ) -> WrapE<'a, A, Result, 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( - wa: WrapE<'a, Result, E0, Self>, - ) -> WrapE<'a, A, Result, Self> { - > 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, >::W>; diff --git a/src/func/fail.rs b/src/func/fail.rs new file mode 100644 index 0000000..fd75f4c --- /dev/null +++ b/src/func/fail.rs @@ -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(e: E) -> Self::F; +} + +/// Equivalent of Haskell's `MonadFail`. Auto-implemented for all [`Fail`]`+`[`Monad`]. +/// +/// +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: MonadFail<'a, E> + where + E: 'a; + + /// Associated infallible [`Monad`]. + type T: Monad<'a>; + + fn unstuff(wa: WrapE<'a, A, E, Self>) -> Wrap<'a, Result, Self::T>; + + fn stuff(fa: Wrap<'a, Result, Self::T>) -> WrapE<'a, A, E, Self>; + + /// Equivalent of [`Result::map_err`]. + fn map_err( + 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( + 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( + wa: WrapE<'a, A, E0, Self>, + f: impl 'a + FnOnce(Result) -> WrapE<'a, B, E1, Self>, + ) -> WrapE<'a, B, E1, Self> { + Self::stuff(::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( + wwa: WrapE<'a, WrapE<'a, A, E0, Self>, E1, Self>, + ) -> WrapE<'a, A, Result, 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( + wa: WrapE<'a, Result, E0, Self>, + ) -> WrapE<'a, A, Result, Self> { + > 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, >::W>;