//! Helper [Monad]s to defer execution until necessary. //! Wrapped value is just a box pointing to the constructor function. //! //! Due to semantical laziness, //! [`LazyClass::replace`] and [`LazyClass::discard_first`]/[`LazyClass::discard_second`] //! actually fully cancel the "unnecessary" computation. //! //! For stackless execution see [`super::stackless`]. use std::{cell::RefCell, rc::Rc}; use crate::func::*; #[derive(CovariantFunctor)] pub struct LazyClass; impl WeakFunctor for LazyClass { type F<'a, A: 'a> = Box A>; } impl Functor for LazyClass { fn fmap<'a, A: 'a, B: 'a>(f: impl 'a + FnOnce(A) -> B, fa: Self::F<'a, A>) -> Self::F<'a, B> { Box::new(|| f(fa())) } fn replace<'a, A: 'a, B: 'a>(fa: Self::F<'a, A>, b: B) -> Self::F<'a, B> { drop(fa); Box::new(|| b) } fn void<'a, A: 'a>(fa: Self::F<'a, A>) -> Self::F<'a, ()> { drop(fa); Box::new(|| ()) } } impl Pure for LazyClass { fn pure<'a, A: 'a>(a: A) -> Self::F<'a, A> { Box::new(|| a) } } impl ApplicativeSeq for LazyClass { fn seq<'a, A: 'a, B: 'a>( ff: Self::F<'a, impl 'a + FnOnce(A) -> B>, fa: Self::F<'a, A>, ) -> Self::F<'a, B> { Box::new(|| ff()(fa())) } } impl ApplicativeLA2 for LazyClass { fn la2<'a, A: 'a, B: 'a, C: 'a>( f: impl 'a + FnOnce(A, B) -> C, fa: Self::F<'a, A>, fb: Self::F<'a, B>, ) -> Self::F<'a, C> { Box::new(|| f(fa(), fb())) } } impl ApplicativeTuple for LazyClass { fn tuple<'a, A: 'a, B: 'a>((fa, fb): (Self::F<'a, A>, Self::F<'a, B>)) -> Self::F<'a, (A, B)> where Self: 'a, { Box::new(|| (fa(), fb())) } } impl Applicative for LazyClass { fn discard_first<'a, A: 'a, B: 'a>(fa: Self::F<'a, A>, fb: Self::F<'a, B>) -> Self::F<'a, B> { drop(fa); fb } fn discard_second<'a, A: 'a, B: 'a>(fa: Self::F<'a, A>, fb: Self::F<'a, B>) -> Self::F<'a, A> { drop(fb); fa } } impl Monad for LazyClass { fn bind<'a, A: 'a, B: 'a>( fa: Self::F<'a, A>, f: impl 'a + FnOnce(A) -> Self::F<'a, B>, ) -> Self::F<'a, B> { Box::new(|| f(fa())()) } fn ibind<'a, A: 'a, B: 'a>( mut a: A, mut f: impl 'a + FnMut(A) -> Self::F<'a, ControlFlow>, ) -> Self::F<'a, B> where Self: 'a, { Box::new(move || loop { match f(a)() { ControlFlow::Continue(next_a) => a = next_a, ControlFlow::Break(b) => return b, }; }) } 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> { Box::new(|| ffa()()) } } fn unshare<'a, A: 'a + Clone>(shared: &mut Option A>>) -> A { let a = shared.take().expect( "cannot evaluate a missing shared lazy value. probably, the shared value depends on itself", )(); let cloned = a.clone(); *shared = Some(Box::new(|| cloned)); a } impl SharedFunctor for LazyClass { type Shared<'a, A: 'a + Clone> = Rc A>>>> where Self: 'a; fn share<'a, A: 'a + Clone>(fa: Self::F<'a, A>) -> Self::Shared<'a, A> where Self: 'a, { Rc::new(RefCell::new(Some(fa))) } fn unshare<'a, A: 'a + Clone>(sa: Self::Shared<'a, A>) -> Self::F<'a, A> where Self: 'a, { Box::new(move || unshare(&mut *sa.borrow_mut())) } }