diff --git a/src/func.rs b/src/func.rs index 1efdf45..0dfe28f 100644 --- a/src/func.rs +++ b/src/func.rs @@ -9,18 +9,20 @@ pub mod classes; pub mod clone_func; +mod controlflow; pub mod copy_func; pub mod derivations; -mod istate; #[cfg(test)] pub mod test_suite; #[cfg(test)] pub mod tests; -pub use self::istate::IState; -use self::istate::IStateClass; +pub use std::ops::ControlFlow; + pub use radn_derive::{CovariantFunctor, SharedFunctor}; +pub use self::controlflow::ControlFlowClass; + /// Part of Haskell's `Functor f` responsible to use `f a`. /// /// @@ -177,7 +179,7 @@ pub trait Monad: Applicative { /// On practice, you shouldn't be using [`Monad::bind`]/[`Pure::pure`]/[`Functor::fmap`] here. fn ibind<'a, A: 'a, B: 'a>( a: A, - f: impl 'a + FnMut(A) -> Self::F<'a, IState>, + f: impl 'a + FnMut(A) -> Self::F<'a, ControlFlow>, ) -> Self::F<'a, B> where Self: 'a; @@ -222,11 +224,13 @@ pub trait Alternative: Applicative { /// Represents wrapped results which are instantly available. pub trait LocalFunctor: WeakFunctor { /// Extract iteration state, if successful. - fn unstuff<'a, A: 'a, B: 'a>(state: Self::F<'a, IState>) -> IState> + fn unstuff<'a, A: 'a, B: 'a>( + state: Self::F<'a, ControlFlow>, + ) -> ControlFlow, A> where Self: 'a, { - Self::stuff::<_, IStateClass>(state) + Self::stuff::<_, ControlFlowClass>(state) } /// Stuff wrapped result into another functor. diff --git a/src/func/classes/composition.rs b/src/func/classes/composition.rs index c614de7..7261f69 100644 --- a/src/func/classes/composition.rs +++ b/src/func/classes/composition.rs @@ -101,7 +101,7 @@ impl Monad for CompositionClass { fn ibind<'a, A: 'a, B: 'a>( a: A, - mut f: impl 'a + FnMut(A) -> Self::F<'a, IState>, + mut f: impl 'a + FnMut(A) -> Self::F<'a, ControlFlow>, ) -> Self::F<'a, B> where Self: 'a, @@ -132,7 +132,9 @@ impl + LocalFunctor> MonadFail for CompositionCl } impl LocalFunctor for CompositionClass { - fn unstuff<'a, A: 'a, B: 'a>(state: Self::F<'a, IState>) -> IState> + fn unstuff<'a, A: 'a, B: 'a>( + state: Self::F<'a, ControlFlow>, + ) -> ControlFlow, A> where Self: 'a, { diff --git a/src/func/classes/future.rs b/src/func/classes/future.rs index db00e22..dbf3e9f 100644 --- a/src/func/classes/future.rs +++ b/src/func/classes/future.rs @@ -89,7 +89,7 @@ impl Monad for FutureClass { fn ibind<'a, A: 'a, B: 'a>( mut a: A, - mut f: impl 'a + FnMut(A) -> Self::F<'a, IState>, + mut f: impl 'a + FnMut(A) -> Self::F<'a, ControlFlow>, ) -> Self::F<'a, B> where Self: 'a, @@ -97,8 +97,8 @@ impl Monad for FutureClass { Box::pin(async move { loop { match f(a).await { - IState::Pending(next_a) => a = next_a, - IState::Done(b) => return b, + ControlFlow::Continue(next_a) => a = next_a, + ControlFlow::Break(b) => return b, }; } }) diff --git a/src/func/classes/lazy.rs b/src/func/classes/lazy.rs index 63169f6..8128dbf 100644 --- a/src/func/classes/lazy.rs +++ b/src/func/classes/lazy.rs @@ -90,15 +90,15 @@ impl Monad for LazyClass { fn ibind<'a, A: 'a, B: 'a>( mut a: A, - mut f: impl 'a + FnMut(A) -> Self::F<'a, IState>, + mut f: impl 'a + FnMut(A) -> Self::F<'a, ControlFlow>, ) -> Self::F<'a, B> where Self: 'a, { Box::new(move || loop { match f(a)() { - IState::Pending(next_a) => a = next_a, - IState::Done(b) => return b, + ControlFlow::Continue(next_a) => a = next_a, + ControlFlow::Break(b) => return b, }; }) } diff --git a/src/func/classes/option.rs b/src/func/classes/option.rs index 4d7f752..8106158 100644 --- a/src/func/classes/option.rs +++ b/src/func/classes/option.rs @@ -94,15 +94,15 @@ impl Monad for OptionClass { fn ibind<'a, A: 'a, B: 'a>( mut a: A, - mut f: impl 'a + FnMut(A) -> Self::F<'a, IState>, + mut f: impl 'a + FnMut(A) -> Self::F<'a, ControlFlow>, ) -> Self::F<'a, B> where Self: 'a, { loop { match f(a)? { - IState::Pending(next_a) => a = next_a, - IState::Done(b) => return Self::pure(b), + ControlFlow::Continue(next_a) => a = next_a, + ControlFlow::Break(b) => return Self::pure(b), }; } } @@ -113,14 +113,16 @@ impl Monad for OptionClass { } impl LocalFunctor for OptionClass { - fn unstuff<'a, A: 'a, B: 'a>(state: Self::F<'a, IState>) -> IState> + fn unstuff<'a, A: 'a, B: 'a>( + state: Self::F<'a, ControlFlow>, + ) -> ControlFlow, A> where Self: 'a, { match state { - Some(IState::Pending(a)) => IState::Pending(a), - Some(IState::Done(b)) => IState::Done(Some(b)), - None => IState::Done(None), + Some(ControlFlow::Continue(a)) => ControlFlow::Continue(a), + Some(ControlFlow::Break(b)) => ControlFlow::Break(Some(b)), + None => ControlFlow::Break(None), } } diff --git a/src/func/classes/result.rs b/src/func/classes/result.rs index 03d4424..0649a60 100644 --- a/src/func/classes/result.rs +++ b/src/func/classes/result.rs @@ -115,15 +115,15 @@ impl Monad for ResultClass { fn ibind<'a, A: 'a, B: 'a>( mut a: A, - mut f: impl 'a + FnMut(A) -> Self::F<'a, IState>, + mut f: impl 'a + FnMut(A) -> Self::F<'a, ControlFlow>, ) -> Self::F<'a, B> where Self: 'a, { loop { match f(a)? { - IState::Pending(next_a) => a = next_a, - IState::Done(b) => return Self::pure(b), + ControlFlow::Continue(next_a) => a = next_a, + ControlFlow::Break(b) => return Self::pure(b), }; } } @@ -137,14 +137,16 @@ impl Monad for ResultClass { } impl LocalFunctor for ResultClass { - fn unstuff<'a, A: 'a, B: 'a>(state: Self::F<'a, IState>) -> IState> + fn unstuff<'a, A: 'a, B: 'a>( + state: Self::F<'a, ControlFlow>, + ) -> ControlFlow, A> where Self: 'a, { match state { - Ok(IState::Pending(a)) => IState::Pending(a), - Ok(IState::Done(b)) => IState::Done(Ok(b)), - Err(e) => IState::Done(Err(e)), + Ok(ControlFlow::Continue(a)) => ControlFlow::Continue(a), + Ok(ControlFlow::Break(b)) => ControlFlow::Break(Ok(b)), + Err(e) => ControlFlow::Break(Err(e)), } } diff --git a/src/func/classes/solo.rs b/src/func/classes/solo.rs index 18d17f8..94b7650 100644 --- a/src/func/classes/solo.rs +++ b/src/func/classes/solo.rs @@ -82,15 +82,15 @@ impl Monad for SoloClass { fn ibind<'a, A: 'a, B: 'a>( mut a: A, - mut f: impl 'a + FnMut(A) -> Self::F<'a, IState>, + mut f: impl 'a + FnMut(A) -> Self::F<'a, ControlFlow>, ) -> Self::F<'a, B> where Self: 'a, { loop { match f(a) { - IState::Pending(next_a) => a = next_a, - IState::Done(b) => return b, + ControlFlow::Continue(next_a) => a = next_a, + ControlFlow::Break(b) => return b, }; } } @@ -101,7 +101,9 @@ impl Monad for SoloClass { } impl LocalFunctor for SoloClass { - fn unstuff<'a, A: 'a, B: 'a>(state: Self::F<'a, IState>) -> IState> + fn unstuff<'a, A: 'a, B: 'a>( + state: Self::F<'a, ControlFlow>, + ) -> ControlFlow, A> where Self: 'a, { diff --git a/src/func/classes/stackless.rs b/src/func/classes/stackless.rs index abbb162..e9b0bf3 100644 --- a/src/func/classes/stackless.rs +++ b/src/func/classes/stackless.rs @@ -226,15 +226,15 @@ impl Monad for StacklessClass { fn ibind<'a, A: 'a, B: 'a>( a: A, - mut f: impl 'a + FnMut(A) -> Self::F<'a, IState>, + mut f: impl 'a + FnMut(A) -> Self::F<'a, ControlFlow>, ) -> Self::F<'a, B> where Self: 'a, { Self::pure(a).bind(move |a| { f(a).bind(|state| match state { - IState::Pending(a) => Self::ibind(a, f), - IState::Done(b) => Self::pure(b), + ControlFlow::Continue(a) => Self::ibind(a, f), + ControlFlow::Break(b) => Self::pure(b), }) }) } diff --git a/src/func/controlflow.rs b/src/func/controlflow.rs new file mode 100644 index 0000000..9f59dbb --- /dev/null +++ b/src/func/controlflow.rs @@ -0,0 +1,30 @@ +use super::*; + +pub struct ControlFlowClass(ControlFlow<(), C>); + +impl WeakFunctor for ControlFlowClass { + type F<'a, A: 'a> = ControlFlow + where + Self: 'a; +} + +impl Functor for ControlFlowClass { + fn fmap<'a, A: 'a, B: 'a>(f: impl 'a + FnOnce(A) -> B, fa: Self::F<'a, A>) -> Self::F<'a, B> + where + Self: 'a, + { + match fa { + ControlFlow::Continue(c) => ControlFlow::Continue(c), + ControlFlow::Break(a) => ControlFlow::Break(f(a)), + } + } +} + +impl Pure for ControlFlowClass { + fn pure<'a, A: 'a>(a: A) -> Self::F<'a, A> + where + Self: 'a, + { + ControlFlow::Break(a) + } +} diff --git a/src/func/istate.rs b/src/func/istate.rs deleted file mode 100644 index 2efd8e4..0000000 --- a/src/func/istate.rs +++ /dev/null @@ -1,44 +0,0 @@ -use super::*; - -/// Represents iteration state. Used in [`Monad::ibind`]. -/// -/// [`IState`] is isomorphic to [`Result`]. -pub enum IState { - /// Loop running. - /// - /// Isomorphic to [`Result::Err`]. - Pending(P), - /// Loop finished. - /// - /// Isomorphic to [`Result::Ok`]. - Done(D), -} - -pub struct IStateClass

(P); - -impl

WeakFunctor for IStateClass

{ - type F<'a, A: 'a> = IState - where - Self: 'a; -} - -impl

Functor for IStateClass

{ - fn fmap<'a, A: 'a, B: 'a>(f: impl 'a + FnOnce(A) -> B, fa: Self::F<'a, A>) -> Self::F<'a, B> - where - Self: 'a, - { - match fa { - IState::Pending(p) => IState::Pending(p), - IState::Done(d) => IState::Done(f(d)), - } - } -} - -impl

Pure for IStateClass

{ - fn pure<'a, A: 'a>(a: A) -> Self::F<'a, A> - where - Self: 'a, - { - IState::Done(a) - } -} diff --git a/src/std/collections/stack.rs b/src/std/collections/stack.rs index 889a5c1..7062074 100644 --- a/src/std/collections/stack.rs +++ b/src/std/collections/stack.rs @@ -158,17 +158,17 @@ impl<'a, Ctx: 'a + Context, A: Mentionable<'a, Ctx>> ExtStack<'a, Ctx, A> for St } fn vec(self) -> StackVecWrapped<'a, Ctx, A> { Ctx::T::ibind((vec![], self), |(mut vec, stack)| match stack { - Nullable::Null(_) => Ctx::T::pure(IState::Done(Ok(vec))), + Nullable::Null(_) => Ctx::T::pure(ControlFlow::Break(Ok(vec))), Nullable::NotNull(point) => Ctx::T::fmap( |resolved| { let node = match resolved { Ok(node) => node, Err(error) => { - return IState::Done(Err(error)); + return ControlFlow::Break(Err(error)); } }; vec.push(node.element.clone()); - IState::Pending((vec, node.rest.clone())) + ControlFlow::Continue((vec, node.rest.clone())) }, point.resolve(), ), diff --git a/src/std/tracing.rs b/src/std/tracing.rs index f021cab..dcc9d00 100644 --- a/src/std/tracing.rs +++ b/src/std/tracing.rs @@ -165,7 +165,7 @@ impl Monad for TracedClass { fn ibind<'a, A: 'a, B: 'a>( mut a: A, - mut f: impl 'a + FnMut(A) -> Self::F<'a, IState>, + mut f: impl 'a + FnMut(A) -> Self::F<'a, ControlFlow>, ) -> Self::F<'a, B> where Self: 'a, @@ -175,8 +175,8 @@ impl Monad for TracedClass { let fa = f(a); t = fa.t.after(t); match fa.a { - IState::Pending(next_a) => a = next_a, - IState::Done(b) => return b.with_trace(t), + ControlFlow::Continue(next_a) => a = next_a, + ControlFlow::Break(b) => return b.with_trace(t), } } } diff --git a/src/testing/counted.rs b/src/testing/counted.rs index 66379a3..edfb673 100644 --- a/src/testing/counted.rs +++ b/src/testing/counted.rs @@ -147,7 +147,7 @@ impl Monad for CountedClass { fn ibind<'a, A: 'a, B: 'a>( mut a: A, - mut f: impl 'a + FnMut(A) -> Self::F<'a, IState>, + mut f: impl 'a + FnMut(A) -> Self::F<'a, ControlFlow>, ) -> Self::F<'a, B> where Self: 'a, @@ -157,8 +157,8 @@ impl Monad for CountedClass { let fa = f(a); n += fa.n; match fa.a { - IState::Pending(next_a) => a = next_a, - IState::Done(b) => return b.with_count(n), + ControlFlow::Continue(next_a) => a = next_a, + ControlFlow::Break(b) => return b.with_count(n), } } }