From 725eb6636e30d114849897ee07aa98a3f417f19a Mon Sep 17 00:00:00 2001 From: timofey Date: Tue, 23 May 2023 21:21:02 +0000 Subject: [PATCH] `MonadFailAnyExt:speculative` --- src/func.rs | 11 ++++ src/func/speculative.rs | 109 ++++++++++++++++++++++++++++++++++++++++ 2 files changed, 120 insertions(+) create mode 100644 src/func/speculative.rs diff --git a/src/func.rs b/src/func.rs index 0475f85..e29e1da 100644 --- a/src/func.rs +++ b/src/func.rs @@ -13,6 +13,7 @@ mod controlflow; pub mod copy_func; pub mod derivations; pub mod instances; +mod speculative; #[cfg(test)] pub mod test_suite; #[cfg(test)] @@ -372,6 +373,16 @@ pub trait MonadFailAnyExt: MonadFailAny { { as Fail>::fail(e) } + + fn speculative<'a, A: 'a, B: 'a, E0: 'a, E1: 'a>( + wwa: as WeakFunctor>::F<'a, as WeakFunctor>::F<'a, A>>, + wwb: as WeakFunctor>::F<'a, as WeakFunctor>::F<'a, B>>, + ) -> > as WeakFunctor>::F<'a, (A, B)> + where + Self: 'a, + { + ::speculative(wwa, wwb) + } } impl MonadFailAnyExt for Fallible {} diff --git a/src/func/speculative.rs b/src/func/speculative.rs new file mode 100644 index 0000000..dedf102 --- /dev/null +++ b/src/func/speculative.rs @@ -0,0 +1,109 @@ +use super::*; + +type Fwa<'a, A, E0, E1, Fallible> = <::T as WeakFunctor>::F< + 'a, + Result<<::W as WeakFunctor>::F<'a, A>, E1>, +>; + +pub trait SpeculativeFail: MonadFailAny { + fn _speculative_a_wb<'a, A: 'a, B: 'a, E0: 'a, E1: 'a>( + a: Result, + wb: Result< as WeakFunctor>::F<'a, B>, E1>, + ) -> > as WeakFunctor>::F<'a, (A, B)> + where + Self: 'a, + { + match wb { + Ok(wb) => match a { + Ok(a) => Self::map_err( as Functor>::fmap(|b| (a, b), wb), Ok), + Err(e0) => Self::fail(Ok(e0)), + }, + Err(e1) => Self::fail(Err(e1)), + } + } + + fn _speculative_a_fwb<'a, A: 'a, B: 'a, E0: 'a, E1: 'a>( + a: Result, + fwb: Fwa<'a, B, E0, E1, Self>, + ) -> > as WeakFunctor>::F<'a, (A, B)> + where + Self: 'a, + { + Self::stuff(::bind(fwb, |wb| { + Self::unstuff(Self::_speculative_a_wb(a, wb)) + })) + } + + fn _speculative_fa_wb<'a, A: 'a, B: 'a, E0: 'a>( + fa: ::F<'a, Result>, + wb: as WeakFunctor>::F<'a, B>, + ) -> as WeakFunctor>::F<'a, (A, B)> + where + Self: 'a, + { + as ApplicativeTuple>::tuple((Self::stuff(fa), wb)) + } + + fn _speculative_wa_fwb<'a, A: 'a, B: 'a, E0: 'a, E1: 'a>( + wa: as WeakFunctor>::F<'a, A>, + fwb: Fwa<'a, B, E0, E1, Self>, + ) -> > as WeakFunctor>::F<'a, (A, B)> + where + Self: 'a, + { + Self::stuff(<::T as Monad>::join( + <::T as Functor>::fmap( + Self::unstuff, + ::select( + |selected| match selected { + Selected::A(a, fwb) => Self::_speculative_a_fwb(a, fwb), + Selected::B(fa, Ok(wb)) => { + Self::map_err(Self::_speculative_fa_wb(fa, wb), Ok) + } + Selected::B(_, Err(e1)) => Self::fail(Err(e1)), + }, + Self::unstuff(wa), + fwb, + ), + ), + )) + } + + fn _speculative_fwa_wb<'a, A: 'a, B: 'a, E0: 'a, E1: 'a>( + fwa: Fwa<'a, A, E0, E1, Self>, + wb: as WeakFunctor>::F<'a, B>, + ) -> > as WeakFunctor>::F<'a, (A, B)> + where + Self: 'a, + { + > as Functor>::fmap( + |(b, a)| (a, b), + Self::_speculative_wa_fwb(wb, fwa), + ) + } + + fn speculative<'a, A: 'a, B: 'a, E0: 'a, E1: 'a>( + wwa: as WeakFunctor>::F<'a, as WeakFunctor>::F<'a, A>>, + wwb: as WeakFunctor>::F<'a, as WeakFunctor>::F<'a, B>>, + ) -> > as WeakFunctor>::F<'a, (A, B)> + where + Self: 'a, + { + Self::stuff(::join(::fmap( + Self::unstuff, + ::select( + |selected| match selected { + Selected::A(Ok(wa), fwb) => Self::_speculative_wa_fwb(wa, fwb), + Selected::A(Err(e1), _) => Self::fail(Err(e1)), + Selected::B(fwa, Ok(wb)) => Self::_speculative_fwa_wb(fwa, wb), + Selected::B(_, Err(e1)) => Self::fail(Err(e1)), + }, + Self::unstuff(wwa), + Self::unstuff(wwb), + ), + ))) + } +} + +impl SpeculativeFail for Fallible {} + \ No newline at end of file