diff --git a/src/func/instances/stackless.rs b/src/func/instances/stackless.rs index 1fc409e..0badc89 100644 --- a/src/func/instances/stackless.rs +++ b/src/func/instances/stackless.rs @@ -11,7 +11,7 @@ use std::{cell::Cell, rc::Rc}; use crate::func::class_prelude::*; use crate::func::derivations::{ApplicativeLA2ViaSeq, ApplicativeTupleViaLA2}; -struct Wrapper<'a, F>(F, PhantomData<&'a ()>); +struct Wrapper(F, PhantomData); trait Atom { fn next<'t>(self: Box) -> Oet<'t> @@ -31,10 +31,7 @@ fn satom<'a, F: 'a + FnOnce() -> Oet<'a>>(f: F) -> Oet<'a> { Some(atom(f)) } -impl<'a, F> Atom for Wrapper<'a, F> -where - F: 'a + FnOnce() -> Oet<'a>, -{ +impl<'a, F: 'a + FnOnce() -> Oet<'a>> Atom for Wrapper<&'a (), F> { fn next<'t>(self: Box) -> Oet<'t> where Self: 't, @@ -67,7 +64,72 @@ impl<'a> EvalTree<'a> { } } -type StackessDyn<'a, A> = dyn 'a + FnOnce(Box) -> Oet<'a>; +trait IntoOet { + fn into_oet<'t>(self: Box, f: Box) -> Oet<'t> + where + Self: 't, + A: 't; +} + +impl<'a, A: 'a, B: 'a, F: 'a + FnOnce(A) -> Stackless<'a, B>> IntoOet + for Wrapper<(&'a (), B), (Stackless<'a, A>, F)> +{ + fn into_oet<'t>(self: Box, f: Box) -> Oet<'t> + where + Self: 't, + A: 't, + { + let cell_l = Rc::new(Cell::new(None)); + let cell_r = cell_l.clone(); + let (sstackless, sf) = self.0; + Some(EvalTree::Composite( + batom(move || sstackless.call(move |a| set_cell(cell_l, a))), + batom(move || { + let stackless = sf(get_cell(cell_r)); + satom(|| stackless.0.into_oet(f)) + }), + )) + } +} + +impl<'a, A: 'a, B: 'a, F: 'a + FnOnce(A) -> B> IntoOet + for Wrapper<(&'a (), B, ()), (Stackless<'a, A>, F)> +{ + fn into_oet<'t>(self: Box, f: Box) -> Oet<'t> + where + Self: 't, + A: 't, + { + let cell_l = Rc::new(Cell::new(None)); + let cell_r = cell_l.clone(); + let (sstackless, sf) = self.0; + Some(EvalTree::Composite( + batom(move || sstackless.call(move |a| set_cell(cell_l, a))), + batom(move || { + let b = sf(get_cell(cell_r)); + satom(|| { + f(b); + None + }) + }), + )) + } +} + +impl IntoOet for Wrapper<(), A> { + fn into_oet<'t>(self: Box, f: Box) -> Oet<'t> + where + Self: 't, + A: 't, + { + satom(|| { + f(self.0); + None + }) + } +} + +type StackessDyn<'a, A> = dyn 'a + IntoOet; pub struct Stackless<'a, A: 'a>(Box>); @@ -86,41 +148,18 @@ fn get_cell(cell: Rc>>) -> A { impl<'a, A: 'a> Stackless<'a, A> { fn call(self, f: impl 'a + FnOnce(A)) -> Oet<'a> { - self.0(Box::new(f)) + self.0.into_oet(Box::new(f)) } /// Method-like equivalent of [`Monad::bind`], /// the preferred way to chain [`Stackless`] and `FnOnce(A) -> Stackless` into [`Stackless`]. pub fn bind(self, f: impl 'a + FnOnce(A) -> Stackless<'a, B>) -> Stackless<'a, B> { - Stackless(Box::new(|takesb| { - let cell_l = Rc::new(Cell::new(None)); - let cell_r = cell_l.clone(); - Some(EvalTree::Composite( - batom(move || self.call(move |a| set_cell(cell_l, a))), - batom(move || { - let stackless = f(get_cell(cell_r)); - satom(|| stackless.0(takesb)) - }), - )) - })) + Stackless(Box::new(Wrapper((self, f), PhantomData))) } /// Method-like equivalent of [`Functor::fmap`]. pub fn map(self, f: impl 'a + FnOnce(A) -> B) -> Stackless<'a, B> { - Stackless(Box::new(|takesb| { - let cell_l = Rc::new(Cell::new(None)); - let cell_r = cell_l.clone(); - Some(EvalTree::Composite( - batom(move || self.call(move |a| set_cell(cell_l, a))), - batom(move || { - let b = f(get_cell(cell_r)); - satom(|| { - takesb(b); - None - }) - }), - )) - })) + Stackless(Box::new(Wrapper((self, f), PhantomData))) } /// Evaluate. Process is loop-like on the inside @@ -138,12 +177,7 @@ impl<'a, A: 'a> Stackless<'a, A> { impl<'a, A: 'a> From for Stackless<'a, A> { fn from(value: A) -> Self { - Stackless(Box::new(|takesa| { - satom(|| { - takesa(value); - None - }) - })) + Stackless(Box::new(Wrapper(value, PhantomData))) } }