parent
ee131e7446
commit
a791fb818f
27
src/func.rs
27
src/func.rs
@ -21,9 +21,10 @@ pub use std::ops::ControlFlow;
|
|||||||
|
|
||||||
pub use radn_derive::{CovariantFunctor, SharedFunctor};
|
pub use radn_derive::{CovariantFunctor, SharedFunctor};
|
||||||
|
|
||||||
use self::controlflow::*;
|
use self::controlflow::{BindableMut, ControlFlowClass};
|
||||||
|
pub use self::controlflow::{Iterative, IterativeWrapped};
|
||||||
|
|
||||||
/// Part of Haskell's `Functor f` responsible to use `f a`.
|
/// Part of Haskell's `Functor f` responsible for having `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>
|
||||||
pub trait WeakFunctor {
|
pub trait WeakFunctor {
|
||||||
@ -172,14 +173,30 @@ pub trait Monad: Applicative {
|
|||||||
where
|
where
|
||||||
Self: 'a;
|
Self: 'a;
|
||||||
|
|
||||||
|
/// Simplified, [`FnMut`] version of [`Monad::iibind`].
|
||||||
|
/// Reasoning for this method existing at all is that
|
||||||
|
/// most usecases are better modelled
|
||||||
|
///
|
||||||
|
/// Note: hypothetically, you can implement [`Monad::iibind`] from [`Monad::ibind`],
|
||||||
|
/// but it's highly discouraged.
|
||||||
|
fn ibind<'a, A: 'a, B: 'a>(
|
||||||
|
a: A,
|
||||||
|
f: impl 'a + FnMut(A) -> Self::F<'a, ControlFlow<B, A>>,
|
||||||
|
) -> Self::F<'a, B>
|
||||||
|
where
|
||||||
|
Self: 'a,
|
||||||
|
{
|
||||||
|
Self::iibind(a, BindableMut::new(f))
|
||||||
|
}
|
||||||
|
|
||||||
/// Kleisli category composition special case used to represent loops.
|
/// Kleisli category composition special case used to represent loops.
|
||||||
/// Included for optimisation and clarity.
|
/// Included for optimisation and clarity.
|
||||||
/// Generally, [`Monad::bind`] should be enough implement it.
|
/// Generally, [`Monad::bind`] should be enough implement it.
|
||||||
/// See [`classes::stackless::StacklessClass::ibind`] for a generic, though less-than ideal, blanket implementation.
|
/// See [`classes::stackless::StacklessClass::ibind`] for a generic, though less-than ideal, blanket implementation.
|
||||||
/// On practice, you shouldn't be using [`Monad::bind`]/[`Pure::pure`]/[`Functor::fmap`] here.
|
/// On practice, you generally shouldn't be using [`Monad::bind`]/[`Pure::pure`]/[`Functor::fmap`] here.
|
||||||
fn ibind<'a, A: 'a, B: 'a>(
|
fn iibind<'a, A: 'a, B: 'a>(
|
||||||
a: A,
|
a: A,
|
||||||
f: impl 'a + FnMut(A) -> Self::F<'a, ControlFlow<B, A>>,
|
f: impl Iterative<'a, T = Self, A = A, B = B>,
|
||||||
) -> Self::F<'a, B>
|
) -> Self::F<'a, B>
|
||||||
where
|
where
|
||||||
Self: 'a;
|
Self: 'a;
|
||||||
|
@ -107,11 +107,21 @@ impl<U: Monad, V: Monad + LocalFunctor> Monad for CompositionClass<U, V> {
|
|||||||
Self: 'a,
|
Self: 'a,
|
||||||
{
|
{
|
||||||
U::ibind(a, move |a| {
|
U::ibind(a, move |a| {
|
||||||
let fx = f(a);
|
let fstate = f(a);
|
||||||
U::fmap(|ustate| V::unstuff(ustate), fx)
|
U::fmap(|ustate| V::unstuff(ustate), fstate)
|
||||||
})
|
})
|
||||||
}
|
}
|
||||||
|
|
||||||
|
fn iibind<'a, A: 'a, B: 'a>(
|
||||||
|
a: A,
|
||||||
|
f: impl Iterative<'a, T = Self, A = A, B = B>,
|
||||||
|
) -> Self::F<'a, B>
|
||||||
|
where
|
||||||
|
Self: 'a,
|
||||||
|
{
|
||||||
|
U::iibind(a, ComposedBindable(f))
|
||||||
|
}
|
||||||
|
|
||||||
fn join<'a, A: 'a>(ffa: Self::F<'a, Self::F<'a, A>>) -> Self::F<'a, A>
|
fn join<'a, A: 'a>(ffa: Self::F<'a, Self::F<'a, A>>) -> Self::F<'a, A>
|
||||||
where
|
where
|
||||||
Self::F<'a, A>: 'a,
|
Self::F<'a, A>: 'a,
|
||||||
@ -121,6 +131,33 @@ impl<U: Monad, V: Monad + LocalFunctor> Monad for CompositionClass<U, V> {
|
|||||||
}
|
}
|
||||||
}
|
}
|
||||||
|
|
||||||
|
struct ComposedBindable<F>(F);
|
||||||
|
|
||||||
|
impl<
|
||||||
|
'a,
|
||||||
|
U: 'a + Monad,
|
||||||
|
V: 'a + Monad + LocalFunctor,
|
||||||
|
F: Iterative<'a, T = CompositionClass<U, V>>,
|
||||||
|
> Iterative<'a> for ComposedBindable<F>
|
||||||
|
{
|
||||||
|
type A = F::A;
|
||||||
|
type B = <V as WeakFunctor>::F<'a, F::B>;
|
||||||
|
type T = U;
|
||||||
|
|
||||||
|
fn iterate(self, a: Self::A) -> IterativeWrapped<'a, Self> {
|
||||||
|
let fstate = self.0.iterate(a);
|
||||||
|
U::fmap(
|
||||||
|
|ustate| match V::unstuff(ustate) {
|
||||||
|
ControlFlow::Continue((next_a, next_f)) => {
|
||||||
|
ControlFlow::Continue((next_a, ComposedBindable(next_f)))
|
||||||
|
}
|
||||||
|
ControlFlow::Break(b) => ControlFlow::Break(b),
|
||||||
|
},
|
||||||
|
fstate,
|
||||||
|
)
|
||||||
|
}
|
||||||
|
}
|
||||||
|
|
||||||
impl<E, U: Monad, V: MonadFail<E> + LocalFunctor> MonadFail<E> for CompositionClass<U, V> {
|
impl<E, U: Monad, V: MonadFail<E> + LocalFunctor> MonadFail<E> for CompositionClass<U, V> {
|
||||||
fn fail<'a, A: 'a>(e: E) -> Self::F<'a, A>
|
fn fail<'a, A: 'a>(e: E) -> Self::F<'a, A>
|
||||||
where
|
where
|
||||||
|
@ -104,6 +104,23 @@ impl Monad for FutureClass {
|
|||||||
})
|
})
|
||||||
}
|
}
|
||||||
|
|
||||||
|
fn iibind<'a, A: 'a, B: 'a>(
|
||||||
|
mut a: A,
|
||||||
|
mut f: impl Iterative<'a, T = Self, A = A, B = B>,
|
||||||
|
) -> Self::F<'a, B>
|
||||||
|
where
|
||||||
|
Self: 'a,
|
||||||
|
{
|
||||||
|
Box::pin(async move {
|
||||||
|
loop {
|
||||||
|
match f.iterate(a).await {
|
||||||
|
ControlFlow::Continue((next_a, next_f)) => (a, f) = (next_a, next_f),
|
||||||
|
ControlFlow::Break(b) => return b,
|
||||||
|
}
|
||||||
|
}
|
||||||
|
})
|
||||||
|
}
|
||||||
|
|
||||||
fn join<'a, A: 'a>(ffa: Self::F<'a, Self::F<'a, A>>) -> Self::F<'a, A> {
|
fn join<'a, A: 'a>(ffa: Self::F<'a, Self::F<'a, A>>) -> Self::F<'a, A> {
|
||||||
Box::pin(async { ffa.await.await })
|
Box::pin(async { ffa.await.await })
|
||||||
}
|
}
|
||||||
|
@ -103,6 +103,21 @@ impl Monad for LazyClass {
|
|||||||
})
|
})
|
||||||
}
|
}
|
||||||
|
|
||||||
|
fn iibind<'a, A: 'a, B: 'a>(
|
||||||
|
mut a: A,
|
||||||
|
mut f: impl Iterative<'a, T = Self, A = A, B = B>,
|
||||||
|
) -> Self::F<'a, B>
|
||||||
|
where
|
||||||
|
Self: 'a,
|
||||||
|
{
|
||||||
|
loop {
|
||||||
|
match f.iterate(a)() {
|
||||||
|
ControlFlow::Continue((next_a, next_f)) => (a, f) = (next_a, next_f),
|
||||||
|
ControlFlow::Break(b) => return Self::pure(b),
|
||||||
|
}
|
||||||
|
}
|
||||||
|
}
|
||||||
|
|
||||||
fn join<'a, A: 'a>(ffa: Self::F<'a, Self::F<'a, A>>) -> Self::F<'a, A> {
|
fn join<'a, A: 'a>(ffa: Self::F<'a, Self::F<'a, A>>) -> Self::F<'a, A> {
|
||||||
Box::new(|| ffa()())
|
Box::new(|| ffa()())
|
||||||
}
|
}
|
||||||
|
@ -107,6 +107,21 @@ impl Monad for OptionClass {
|
|||||||
}
|
}
|
||||||
}
|
}
|
||||||
|
|
||||||
|
fn iibind<'a, A: 'a, B: 'a>(
|
||||||
|
mut a: A,
|
||||||
|
mut f: impl Iterative<'a, T = Self, A = A, B = B>,
|
||||||
|
) -> Self::F<'a, B>
|
||||||
|
where
|
||||||
|
Self: 'a,
|
||||||
|
{
|
||||||
|
loop {
|
||||||
|
match f.iterate(a)? {
|
||||||
|
ControlFlow::Continue((next_a, next_f)) => (a, f) = (next_a, next_f),
|
||||||
|
ControlFlow::Break(b) => return Self::pure(b),
|
||||||
|
}
|
||||||
|
}
|
||||||
|
}
|
||||||
|
|
||||||
fn join<'a, A: 'a>(ffa: Self::F<'a, Self::F<'a, A>>) -> Self::F<'a, A> {
|
fn join<'a, A: 'a>(ffa: Self::F<'a, Self::F<'a, A>>) -> Self::F<'a, A> {
|
||||||
ffa?
|
ffa?
|
||||||
}
|
}
|
||||||
|
@ -128,6 +128,21 @@ impl<E> Monad for ResultClass<E> {
|
|||||||
}
|
}
|
||||||
}
|
}
|
||||||
|
|
||||||
|
fn iibind<'a, A: 'a, B: 'a>(
|
||||||
|
mut a: A,
|
||||||
|
mut f: impl Iterative<'a, T = Self, A = A, B = B>,
|
||||||
|
) -> Self::F<'a, B>
|
||||||
|
where
|
||||||
|
Self: 'a,
|
||||||
|
{
|
||||||
|
loop {
|
||||||
|
match f.iterate(a)? {
|
||||||
|
ControlFlow::Continue((next_a, next_f)) => (a, f) = (next_a, next_f),
|
||||||
|
ControlFlow::Break(b) => return Self::pure(b),
|
||||||
|
}
|
||||||
|
}
|
||||||
|
}
|
||||||
|
|
||||||
fn join<'a, A: 'a>(ffa: Self::F<'a, Self::F<'a, A>>) -> Self::F<'a, A>
|
fn join<'a, A: 'a>(ffa: Self::F<'a, Self::F<'a, A>>) -> Self::F<'a, A>
|
||||||
where
|
where
|
||||||
Self: 'a,
|
Self: 'a,
|
||||||
|
@ -95,6 +95,21 @@ impl Monad for SoloClass {
|
|||||||
}
|
}
|
||||||
}
|
}
|
||||||
|
|
||||||
|
fn iibind<'a, A: 'a, B: 'a>(
|
||||||
|
mut a: A,
|
||||||
|
mut f: impl Iterative<'a, T = Self, A = A, B = B>,
|
||||||
|
) -> Self::F<'a, B>
|
||||||
|
where
|
||||||
|
Self: 'a,
|
||||||
|
{
|
||||||
|
loop {
|
||||||
|
match f.iterate(a) {
|
||||||
|
ControlFlow::Continue((new_a, new_f)) => (a, f) = (new_a, new_f),
|
||||||
|
ControlFlow::Break(b) => return b,
|
||||||
|
}
|
||||||
|
}
|
||||||
|
}
|
||||||
|
|
||||||
fn join<'a, A: 'a>(ffa: Self::F<'a, Self::F<'a, A>>) -> Self::F<'a, A> {
|
fn join<'a, A: 'a>(ffa: Self::F<'a, Self::F<'a, A>>) -> Self::F<'a, A> {
|
||||||
ffa
|
ffa
|
||||||
}
|
}
|
||||||
|
@ -233,7 +233,22 @@ impl Monad for StacklessClass {
|
|||||||
{
|
{
|
||||||
Self::pure(a).bind(move |a| {
|
Self::pure(a).bind(move |a| {
|
||||||
f(a).bind(|state| match state {
|
f(a).bind(|state| match state {
|
||||||
ControlFlow::Continue(a) => Self::ibind(a, f),
|
ControlFlow::Continue(next_a) => Self::ibind(next_a, f),
|
||||||
|
ControlFlow::Break(b) => Self::pure(b),
|
||||||
|
})
|
||||||
|
})
|
||||||
|
}
|
||||||
|
|
||||||
|
fn iibind<'a, A: 'a, B: 'a>(
|
||||||
|
a: A,
|
||||||
|
f: impl Iterative<'a, T = Self, A = A, B = B>,
|
||||||
|
) -> Self::F<'a, B>
|
||||||
|
where
|
||||||
|
Self: 'a,
|
||||||
|
{
|
||||||
|
Self::pure(a).bind(move |a| {
|
||||||
|
f.iterate(a).bind(|state| match state {
|
||||||
|
ControlFlow::Continue((next_a, next_f)) => Self::iibind(next_a, next_f),
|
||||||
ControlFlow::Break(b) => Self::pure(b),
|
ControlFlow::Break(b) => Self::pure(b),
|
||||||
})
|
})
|
||||||
})
|
})
|
||||||
|
@ -1,3 +1,5 @@
|
|||||||
|
use std::marker::PhantomData;
|
||||||
|
|
||||||
use super::*;
|
use super::*;
|
||||||
|
|
||||||
pub struct ControlFlowClass<C>(ControlFlow<(), C>);
|
pub struct ControlFlowClass<C>(ControlFlow<(), C>);
|
||||||
@ -28,3 +30,60 @@ impl<C> Pure for ControlFlowClass<C> {
|
|||||||
ControlFlow::Break(a)
|
ControlFlow::Break(a)
|
||||||
}
|
}
|
||||||
}
|
}
|
||||||
|
|
||||||
|
/// Next [Iterative] state, wrapped.
|
||||||
|
pub type IterativeWrapped<'a, G> = <<G as Iterative<'a>>::T as WeakFunctor>::F<
|
||||||
|
'a,
|
||||||
|
ControlFlow<<G as Iterative<'a>>::B, (<G as Iterative<'a>>::A, G)>,
|
||||||
|
>;
|
||||||
|
|
||||||
|
/// Value passed to [`Monad::iibind`].
|
||||||
|
pub trait Iterative<'a>: 'a + Sized {
|
||||||
|
/// [`ControlFlow::Continue`]
|
||||||
|
type A: 'a;
|
||||||
|
/// [`ControlFlow::Break`]
|
||||||
|
type B: 'a;
|
||||||
|
/// Corresponding [`WeakFunctor`].
|
||||||
|
type T: 'a + ?Sized + WeakFunctor;
|
||||||
|
/// Get next state.
|
||||||
|
fn iterate(self, a: Self::A) -> IterativeWrapped<'a, Self>;
|
||||||
|
}
|
||||||
|
|
||||||
|
pub struct BindableMut<T: ?Sized, A, B, F>(F, PhantomData<A>, PhantomData<B>, PhantomData<T>);
|
||||||
|
|
||||||
|
impl<
|
||||||
|
'a,
|
||||||
|
T: 'a + ?Sized + Functor,
|
||||||
|
A: 'a,
|
||||||
|
B: 'a,
|
||||||
|
F: 'a + FnMut(A) -> T::F<'a, ControlFlow<B, A>>,
|
||||||
|
> BindableMut<T, A, B, F>
|
||||||
|
{
|
||||||
|
pub fn new(f: F) -> Self {
|
||||||
|
BindableMut(f, PhantomData, PhantomData, PhantomData)
|
||||||
|
}
|
||||||
|
}
|
||||||
|
|
||||||
|
impl<
|
||||||
|
'a,
|
||||||
|
T: 'a + ?Sized + Functor,
|
||||||
|
A: 'a,
|
||||||
|
B: 'a,
|
||||||
|
F: 'a + FnMut(A) -> T::F<'a, ControlFlow<B, A>>,
|
||||||
|
> Iterative<'a> for BindableMut<T, A, B, F>
|
||||||
|
{
|
||||||
|
type A = A;
|
||||||
|
type B = B;
|
||||||
|
type T = T;
|
||||||
|
|
||||||
|
fn iterate(mut self, a: Self::A) -> IterativeWrapped<'a, Self> {
|
||||||
|
let fa = self.0(a);
|
||||||
|
T::fmap(
|
||||||
|
move |state| match state {
|
||||||
|
ControlFlow::Continue(next_a) => ControlFlow::Continue((next_a, self)),
|
||||||
|
ControlFlow::Break(b) => ControlFlow::Break(b),
|
||||||
|
},
|
||||||
|
fa,
|
||||||
|
)
|
||||||
|
}
|
||||||
|
}
|
||||||
|
@ -182,6 +182,24 @@ impl Monad for TracedClass {
|
|||||||
}
|
}
|
||||||
}
|
}
|
||||||
|
|
||||||
|
fn iibind<'a, A: 'a, B: 'a>(
|
||||||
|
mut a: A,
|
||||||
|
mut f: impl Iterative<'a, T = Self, A = A, B = B>,
|
||||||
|
) -> Self::F<'a, B>
|
||||||
|
where
|
||||||
|
Self: 'a,
|
||||||
|
{
|
||||||
|
let mut t = TraceBox::pure();
|
||||||
|
loop {
|
||||||
|
let fa = f.iterate(a);
|
||||||
|
t = fa.t.after(t);
|
||||||
|
match fa.a {
|
||||||
|
ControlFlow::Continue((next_a, next_f)) => (a, f) = (next_a, next_f),
|
||||||
|
ControlFlow::Break(b) => return b.with_trace(t),
|
||||||
|
}
|
||||||
|
}
|
||||||
|
}
|
||||||
|
|
||||||
fn join<'a, A: 'a>(ffa: Self::F<'a, Self::F<'a, A>>) -> Self::F<'a, A>
|
fn join<'a, A: 'a>(ffa: Self::F<'a, Self::F<'a, A>>) -> Self::F<'a, A>
|
||||||
where
|
where
|
||||||
Self::F<'a, A>: 'a,
|
Self::F<'a, A>: 'a,
|
||||||
|
@ -164,6 +164,24 @@ impl Monad for CountedClass {
|
|||||||
}
|
}
|
||||||
}
|
}
|
||||||
|
|
||||||
|
fn iibind<'a, A: 'a, B: 'a>(
|
||||||
|
mut a: A,
|
||||||
|
mut f: impl Iterative<'a, T = Self, A = A, B = B>,
|
||||||
|
) -> Self::F<'a, B>
|
||||||
|
where
|
||||||
|
Self: 'a,
|
||||||
|
{
|
||||||
|
let mut n = 0;
|
||||||
|
loop {
|
||||||
|
let fa = f.iterate(a);
|
||||||
|
n += fa.n;
|
||||||
|
match fa.a {
|
||||||
|
ControlFlow::Continue((next_a, next_f)) => (a, f) = (next_a, next_f),
|
||||||
|
ControlFlow::Break(b) => return b.with_count(n),
|
||||||
|
}
|
||||||
|
}
|
||||||
|
}
|
||||||
|
|
||||||
fn join<'a, A: 'a>(ffa: Self::F<'a, Self::F<'a, A>>) -> Self::F<'a, A>
|
fn join<'a, A: 'a>(ffa: Self::F<'a, Self::F<'a, A>>) -> Self::F<'a, A>
|
||||||
where
|
where
|
||||||
Self::F<'a, A>: 'a,
|
Self::F<'a, A>: 'a,
|
||||||
|
Loading…
Reference in New Issue
Block a user