ControlFlow

closes #6
This commit is contained in:
AF 2023-04-27 05:26:07 +00:00
parent b05326089d
commit 73e9b9efb3
13 changed files with 86 additions and 88 deletions

View File

@ -9,18 +9,20 @@
pub mod classes; pub mod classes;
pub mod clone_func; pub mod clone_func;
mod controlflow;
pub mod copy_func; pub mod copy_func;
pub mod derivations; pub mod derivations;
mod istate;
#[cfg(test)] #[cfg(test)]
pub mod test_suite; pub mod test_suite;
#[cfg(test)] #[cfg(test)]
pub mod tests; pub mod tests;
pub use self::istate::IState; pub use std::ops::ControlFlow;
use self::istate::IStateClass;
pub use radn_derive::{CovariantFunctor, SharedFunctor}; pub use radn_derive::{CovariantFunctor, SharedFunctor};
pub use self::controlflow::ControlFlowClass;
/// Part of Haskell's `Functor f` responsible to use `f a`. /// Part of Haskell's `Functor f` responsible to use `f a`.
/// ///
/// <https://hackage.haskell.org/package/base-4.18.0.0/docs/Data-Functor.html> /// <https://hackage.haskell.org/package/base-4.18.0.0/docs/Data-Functor.html>
@ -177,7 +179,7 @@ pub trait Monad: Applicative {
/// On practice, you shouldn't be using [`Monad::bind`]/[`Pure::pure`]/[`Functor::fmap`] here. /// On practice, you shouldn't be using [`Monad::bind`]/[`Pure::pure`]/[`Functor::fmap`] here.
fn ibind<'a, A: 'a, B: 'a>( fn ibind<'a, A: 'a, B: 'a>(
a: A, a: A,
f: impl 'a + FnMut(A) -> Self::F<'a, IState<A, B>>, f: impl 'a + FnMut(A) -> Self::F<'a, ControlFlow<B, A>>,
) -> Self::F<'a, B> ) -> Self::F<'a, B>
where where
Self: 'a; Self: 'a;
@ -222,11 +224,13 @@ pub trait Alternative: Applicative {
/// Represents wrapped results which are instantly available. /// Represents wrapped results which are instantly available.
pub trait LocalFunctor: WeakFunctor { pub trait LocalFunctor: WeakFunctor {
/// Extract iteration state, if successful. /// Extract iteration state, if successful.
fn unstuff<'a, A: 'a, B: 'a>(state: Self::F<'a, IState<A, B>>) -> IState<A, Self::F<'a, B>> fn unstuff<'a, A: 'a, B: 'a>(
state: Self::F<'a, ControlFlow<B, A>>,
) -> ControlFlow<Self::F<'a, B>, A>
where where
Self: 'a, Self: 'a,
{ {
Self::stuff::<_, IStateClass<A>>(state) Self::stuff::<_, ControlFlowClass<A>>(state)
} }
/// Stuff wrapped result into another functor. /// Stuff wrapped result into another functor.

View File

@ -101,7 +101,7 @@ impl<U: Monad, V: Monad + LocalFunctor> Monad for CompositionClass<U, V> {
fn ibind<'a, A: 'a, B: 'a>( fn ibind<'a, A: 'a, B: 'a>(
a: A, a: A,
mut f: impl 'a + FnMut(A) -> Self::F<'a, IState<A, B>>, mut f: impl 'a + FnMut(A) -> Self::F<'a, ControlFlow<B, A>>,
) -> Self::F<'a, B> ) -> Self::F<'a, B>
where where
Self: 'a, Self: 'a,
@ -132,7 +132,9 @@ impl<E, U: Monad, V: MonadFail<E> + LocalFunctor> MonadFail<E> for CompositionCl
} }
impl<U: LocalFunctor + Functor, V: LocalFunctor> LocalFunctor for CompositionClass<U, V> { impl<U: LocalFunctor + Functor, V: LocalFunctor> LocalFunctor for CompositionClass<U, V> {
fn unstuff<'a, A: 'a, B: 'a>(state: Self::F<'a, IState<A, B>>) -> IState<A, Self::F<'a, B>> fn unstuff<'a, A: 'a, B: 'a>(
state: Self::F<'a, ControlFlow<B, A>>,
) -> ControlFlow<Self::F<'a, B>, A>
where where
Self: 'a, Self: 'a,
{ {

View File

@ -89,7 +89,7 @@ impl Monad for FutureClass {
fn ibind<'a, A: 'a, B: 'a>( fn ibind<'a, A: 'a, B: 'a>(
mut a: A, mut a: A,
mut f: impl 'a + FnMut(A) -> Self::F<'a, IState<A, B>>, mut f: impl 'a + FnMut(A) -> Self::F<'a, ControlFlow<B, A>>,
) -> Self::F<'a, B> ) -> Self::F<'a, B>
where where
Self: 'a, Self: 'a,
@ -97,8 +97,8 @@ impl Monad for FutureClass {
Box::pin(async move { Box::pin(async move {
loop { loop {
match f(a).await { match f(a).await {
IState::Pending(next_a) => a = next_a, ControlFlow::Continue(next_a) => a = next_a,
IState::Done(b) => return b, ControlFlow::Break(b) => return b,
}; };
} }
}) })

View File

@ -90,15 +90,15 @@ impl Monad for LazyClass {
fn ibind<'a, A: 'a, B: 'a>( fn ibind<'a, A: 'a, B: 'a>(
mut a: A, mut a: A,
mut f: impl 'a + FnMut(A) -> Self::F<'a, IState<A, B>>, mut f: impl 'a + FnMut(A) -> Self::F<'a, ControlFlow<B, A>>,
) -> Self::F<'a, B> ) -> Self::F<'a, B>
where where
Self: 'a, Self: 'a,
{ {
Box::new(move || loop { Box::new(move || loop {
match f(a)() { match f(a)() {
IState::Pending(next_a) => a = next_a, ControlFlow::Continue(next_a) => a = next_a,
IState::Done(b) => return b, ControlFlow::Break(b) => return b,
}; };
}) })
} }

View File

@ -94,15 +94,15 @@ impl Monad for OptionClass {
fn ibind<'a, A: 'a, B: 'a>( fn ibind<'a, A: 'a, B: 'a>(
mut a: A, mut a: A,
mut f: impl 'a + FnMut(A) -> Self::F<'a, IState<A, B>>, mut f: impl 'a + FnMut(A) -> Self::F<'a, ControlFlow<B, A>>,
) -> Self::F<'a, B> ) -> Self::F<'a, B>
where where
Self: 'a, Self: 'a,
{ {
loop { loop {
match f(a)? { match f(a)? {
IState::Pending(next_a) => a = next_a, ControlFlow::Continue(next_a) => a = next_a,
IState::Done(b) => return Self::pure(b), ControlFlow::Break(b) => return Self::pure(b),
}; };
} }
} }
@ -113,14 +113,16 @@ impl Monad for OptionClass {
} }
impl LocalFunctor for OptionClass { impl LocalFunctor for OptionClass {
fn unstuff<'a, A: 'a, B: 'a>(state: Self::F<'a, IState<A, B>>) -> IState<A, Self::F<'a, B>> fn unstuff<'a, A: 'a, B: 'a>(
state: Self::F<'a, ControlFlow<B, A>>,
) -> ControlFlow<Self::F<'a, B>, A>
where where
Self: 'a, Self: 'a,
{ {
match state { match state {
Some(IState::Pending(a)) => IState::Pending(a), Some(ControlFlow::Continue(a)) => ControlFlow::Continue(a),
Some(IState::Done(b)) => IState::Done(Some(b)), Some(ControlFlow::Break(b)) => ControlFlow::Break(Some(b)),
None => IState::Done(None), None => ControlFlow::Break(None),
} }
} }

View File

@ -115,15 +115,15 @@ impl<E> Monad for ResultClass<E> {
fn ibind<'a, A: 'a, B: 'a>( fn ibind<'a, A: 'a, B: 'a>(
mut a: A, mut a: A,
mut f: impl 'a + FnMut(A) -> Self::F<'a, IState<A, B>>, mut f: impl 'a + FnMut(A) -> Self::F<'a, ControlFlow<B, A>>,
) -> Self::F<'a, B> ) -> Self::F<'a, B>
where where
Self: 'a, Self: 'a,
{ {
loop { loop {
match f(a)? { match f(a)? {
IState::Pending(next_a) => a = next_a, ControlFlow::Continue(next_a) => a = next_a,
IState::Done(b) => return Self::pure(b), ControlFlow::Break(b) => return Self::pure(b),
}; };
} }
} }
@ -137,14 +137,16 @@ impl<E> Monad for ResultClass<E> {
} }
impl<E> LocalFunctor for ResultClass<E> { impl<E> LocalFunctor for ResultClass<E> {
fn unstuff<'a, A: 'a, B: 'a>(state: Self::F<'a, IState<A, B>>) -> IState<A, Self::F<'a, B>> fn unstuff<'a, A: 'a, B: 'a>(
state: Self::F<'a, ControlFlow<B, A>>,
) -> ControlFlow<Self::F<'a, B>, A>
where where
Self: 'a, Self: 'a,
{ {
match state { match state {
Ok(IState::Pending(a)) => IState::Pending(a), Ok(ControlFlow::Continue(a)) => ControlFlow::Continue(a),
Ok(IState::Done(b)) => IState::Done(Ok(b)), Ok(ControlFlow::Break(b)) => ControlFlow::Break(Ok(b)),
Err(e) => IState::Done(Err(e)), Err(e) => ControlFlow::Break(Err(e)),
} }
} }

View File

@ -82,15 +82,15 @@ impl Monad for SoloClass {
fn ibind<'a, A: 'a, B: 'a>( fn ibind<'a, A: 'a, B: 'a>(
mut a: A, mut a: A,
mut f: impl 'a + FnMut(A) -> Self::F<'a, IState<A, B>>, mut f: impl 'a + FnMut(A) -> Self::F<'a, ControlFlow<B, A>>,
) -> Self::F<'a, B> ) -> Self::F<'a, B>
where where
Self: 'a, Self: 'a,
{ {
loop { loop {
match f(a) { match f(a) {
IState::Pending(next_a) => a = next_a, ControlFlow::Continue(next_a) => a = next_a,
IState::Done(b) => return b, ControlFlow::Break(b) => return b,
}; };
} }
} }
@ -101,7 +101,9 @@ impl Monad for SoloClass {
} }
impl LocalFunctor for SoloClass { impl LocalFunctor for SoloClass {
fn unstuff<'a, A: 'a, B: 'a>(state: Self::F<'a, IState<A, B>>) -> IState<A, Self::F<'a, B>> fn unstuff<'a, A: 'a, B: 'a>(
state: Self::F<'a, ControlFlow<B, A>>,
) -> ControlFlow<Self::F<'a, B>, A>
where where
Self: 'a, Self: 'a,
{ {

View File

@ -226,15 +226,15 @@ impl Monad for StacklessClass {
fn ibind<'a, A: 'a, B: 'a>( fn ibind<'a, A: 'a, B: 'a>(
a: A, a: A,
mut f: impl 'a + FnMut(A) -> Self::F<'a, IState<A, B>>, mut f: impl 'a + FnMut(A) -> Self::F<'a, ControlFlow<B, A>>,
) -> Self::F<'a, B> ) -> Self::F<'a, B>
where where
Self: 'a, Self: 'a,
{ {
Self::pure(a).bind(move |a| { Self::pure(a).bind(move |a| {
f(a).bind(|state| match state { f(a).bind(|state| match state {
IState::Pending(a) => Self::ibind(a, f), ControlFlow::Continue(a) => Self::ibind(a, f),
IState::Done(b) => Self::pure(b), ControlFlow::Break(b) => Self::pure(b),
}) })
}) })
} }

30
src/func/controlflow.rs Normal file
View File

@ -0,0 +1,30 @@
use super::*;
pub struct ControlFlowClass<C>(ControlFlow<(), C>);
impl<C> WeakFunctor for ControlFlowClass<C> {
type F<'a, A: 'a> = ControlFlow<A, C>
where
Self: 'a;
}
impl<C> Functor for ControlFlowClass<C> {
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<C> Pure for ControlFlowClass<C> {
fn pure<'a, A: 'a>(a: A) -> Self::F<'a, A>
where
Self: 'a,
{
ControlFlow::Break(a)
}
}

View File

@ -1,44 +0,0 @@
use super::*;
/// Represents iteration state. Used in [`Monad::ibind`].
///
/// [`IState<P, D>`] is isomorphic to [`Result<D, P>`].
pub enum IState<P, D> {
/// Loop running.
///
/// Isomorphic to [`Result::Err`].
Pending(P),
/// Loop finished.
///
/// Isomorphic to [`Result::Ok`].
Done(D),
}
pub struct IStateClass<P>(P);
impl<P> WeakFunctor for IStateClass<P> {
type F<'a, A: 'a> = IState<P, A>
where
Self: 'a;
}
impl<P> Functor for IStateClass<P> {
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<P> Pure for IStateClass<P> {
fn pure<'a, A: 'a>(a: A) -> Self::F<'a, A>
where
Self: 'a,
{
IState::Done(a)
}
}

View File

@ -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> { fn vec(self) -> StackVecWrapped<'a, Ctx, A> {
Ctx::T::ibind((vec![], self), |(mut vec, stack)| match stack { 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( Nullable::NotNull(point) => Ctx::T::fmap(
|resolved| { |resolved| {
let node = match resolved { let node = match resolved {
Ok(node) => node, Ok(node) => node,
Err(error) => { Err(error) => {
return IState::Done(Err(error)); return ControlFlow::Break(Err(error));
} }
}; };
vec.push(node.element.clone()); vec.push(node.element.clone());
IState::Pending((vec, node.rest.clone())) ControlFlow::Continue((vec, node.rest.clone()))
}, },
point.resolve(), point.resolve(),
), ),

View File

@ -165,7 +165,7 @@ impl Monad for TracedClass {
fn ibind<'a, A: 'a, B: 'a>( fn ibind<'a, A: 'a, B: 'a>(
mut a: A, mut a: A,
mut f: impl 'a + FnMut(A) -> Self::F<'a, IState<A, B>>, mut f: impl 'a + FnMut(A) -> Self::F<'a, ControlFlow<B, A>>,
) -> Self::F<'a, B> ) -> Self::F<'a, B>
where where
Self: 'a, Self: 'a,
@ -175,8 +175,8 @@ impl Monad for TracedClass {
let fa = f(a); let fa = f(a);
t = fa.t.after(t); t = fa.t.after(t);
match fa.a { match fa.a {
IState::Pending(next_a) => a = next_a, ControlFlow::Continue(next_a) => a = next_a,
IState::Done(b) => return b.with_trace(t), ControlFlow::Break(b) => return b.with_trace(t),
} }
} }
} }

View File

@ -147,7 +147,7 @@ impl Monad for CountedClass {
fn ibind<'a, A: 'a, B: 'a>( fn ibind<'a, A: 'a, B: 'a>(
mut a: A, mut a: A,
mut f: impl 'a + FnMut(A) -> Self::F<'a, IState<A, B>>, mut f: impl 'a + FnMut(A) -> Self::F<'a, ControlFlow<B, A>>,
) -> Self::F<'a, B> ) -> Self::F<'a, B>
where where
Self: 'a, Self: 'a,
@ -157,8 +157,8 @@ impl Monad for CountedClass {
let fa = f(a); let fa = f(a);
n += fa.n; n += fa.n;
match fa.a { match fa.a {
IState::Pending(next_a) => a = next_a, ControlFlow::Continue(next_a) => a = next_a,
IState::Done(b) => return b.with_count(n), ControlFlow::Break(b) => return b.with_count(n),
} }
} }
} }