//! Helper [Monad]s to defer execution until necessary. //! Wrapped value is just a box pointing to the constructor function. //! //! Due to semantical laziness, //! [`LazyInstance::replace`] and [`LazyInstance::discard_first`]/[`LazyInstance::discard_second`] //! actually fully cancel the "unnecessary" computation. //! //! For stackless execution see [`super::stackless`]. use std::{cell::RefCell, rc::Rc}; use crate::func::*; pub struct LazyInstance; impl WeakFunctor for LazyInstance { type F<'a, A: 'a> = Box A>; } impl<'a> Functor<'a> for LazyInstance { fn fmap(f: impl 'a + FnOnce(A) -> B, fa: Self::Fa) -> Self::Fa { Box::new(|| f(fa())) } fn replace(fa: Self::Fa, b: B) -> Self::Fa { drop(fa); Box::new(|| b) } fn void(fa: Self::Fa) -> Self::Fa<()> { drop(fa); Box::new(|| ()) } } impl<'a> Pure<'a> for LazyInstance { fn pure(a: A) -> Self::Fa { Box::new(|| a) } } impl<'a> ApplicativeSeq<'a> for LazyInstance { fn seq(ff: Self::Fa B>, fa: Self::Fa) -> Self::Fa { Box::new(|| ff()(fa())) } } impl<'a> ApplicativeLA2<'a> for LazyInstance { fn la2( f: impl 'a + FnOnce(A, B) -> C, fa: Self::Fa, fb: Self::Fa, ) -> Self::Fa { Box::new(|| f(fa(), fb())) } } impl<'a> ApplicativeTuple<'a> for LazyInstance { fn tuple((fa, fb): (Self::Fa, Self::Fa)) -> Self::Fa<(A, B)> { Box::new(|| (fa(), fb())) } } impl<'a> ApplicativeSelect<'a> for LazyInstance {} impl<'a> Applicative<'a> for LazyInstance { fn discard_first(fa: Self::Fa, fb: Self::Fa) -> Self::Fa { drop(fa); fb } fn discard_second(fa: Self::Fa, fb: Self::Fa) -> Self::Fa { drop(fb); fa } } impl<'a> Monad<'a> for LazyInstance { fn bind(fa: Self::Fa, f: impl 'a + FnOnce(A) -> Self::Fa) -> Self::Fa { Box::new(|| f(fa())()) } fn iterate(mut f: impl Iterative<'a, T = Self, B = B>) -> Self::Fa { loop { match f.next()() { ControlFlow::Continue(next_f) => f = next_f, ControlFlow::Break(b) => return Self::pure(b), } } } fn join(ffa: Self::Fa>) -> Self::Fa { 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<'a> SharedFunctor<'a> for LazyInstance { type Shared = Rc A>>>>; fn share(fa: Self::Fa) -> Self::Shared { Rc::new(RefCell::new(Some(fa))) } fn unshare(sa: Self::Shared) -> Self::Fa { Box::new(move || unshare(&mut *sa.borrow_mut())) } }