parent
b05326089d
commit
73e9b9efb3
16
src/func.rs
16
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`.
|
||||
///
|
||||
/// <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.
|
||||
fn ibind<'a, A: 'a, B: '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>
|
||||
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<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
|
||||
Self: 'a,
|
||||
{
|
||||
Self::stuff::<_, IStateClass<A>>(state)
|
||||
Self::stuff::<_, ControlFlowClass<A>>(state)
|
||||
}
|
||||
|
||||
/// Stuff wrapped result into another functor.
|
||||
|
@ -101,7 +101,7 @@ impl<U: Monad, V: Monad + LocalFunctor> Monad for CompositionClass<U, V> {
|
||||
|
||||
fn ibind<'a, A: 'a, B: '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>
|
||||
where
|
||||
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> {
|
||||
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
|
||||
Self: 'a,
|
||||
{
|
||||
|
@ -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<A, B>>,
|
||||
mut f: impl 'a + FnMut(A) -> Self::F<'a, ControlFlow<B, A>>,
|
||||
) -> 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,
|
||||
};
|
||||
}
|
||||
})
|
||||
|
@ -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<A, B>>,
|
||||
mut f: impl 'a + FnMut(A) -> Self::F<'a, ControlFlow<B, A>>,
|
||||
) -> 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,
|
||||
};
|
||||
})
|
||||
}
|
||||
|
@ -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<A, B>>,
|
||||
mut f: impl 'a + FnMut(A) -> Self::F<'a, ControlFlow<B, A>>,
|
||||
) -> 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<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
|
||||
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),
|
||||
}
|
||||
}
|
||||
|
||||
|
@ -115,15 +115,15 @@ impl<E> Monad for ResultClass<E> {
|
||||
|
||||
fn ibind<'a, A: 'a, B: '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>
|
||||
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<E> Monad 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
|
||||
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)),
|
||||
}
|
||||
}
|
||||
|
||||
|
@ -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<A, B>>,
|
||||
mut f: impl 'a + FnMut(A) -> Self::F<'a, ControlFlow<B, A>>,
|
||||
) -> 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<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
|
||||
Self: 'a,
|
||||
{
|
||||
|
@ -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<A, B>>,
|
||||
mut f: impl 'a + FnMut(A) -> Self::F<'a, ControlFlow<B, A>>,
|
||||
) -> 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),
|
||||
})
|
||||
})
|
||||
}
|
||||
|
30
src/func/controlflow.rs
Normal file
30
src/func/controlflow.rs
Normal 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)
|
||||
}
|
||||
}
|
@ -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)
|
||||
}
|
||||
}
|
@ -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(),
|
||||
),
|
||||
|
@ -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<A, B>>,
|
||||
mut f: impl 'a + FnMut(A) -> Self::F<'a, ControlFlow<B, A>>,
|
||||
) -> 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),
|
||||
}
|
||||
}
|
||||
}
|
||||
|
@ -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<A, B>>,
|
||||
mut f: impl 'a + FnMut(A) -> Self::F<'a, ControlFlow<B, A>>,
|
||||
) -> 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),
|
||||
}
|
||||
}
|
||||
}
|
||||
|
Loading…
Reference in New Issue
Block a user