simplify TracedClass

This commit is contained in:
AF 2023-05-14 06:13:22 +00:00
parent cb650c81b5
commit 5863532338
7 changed files with 51 additions and 192 deletions

View File

@ -282,7 +282,7 @@ mod tests {
None, None,
None, None,
); );
assert!(traced.a.is_ok()); assert!(traced.value.is_ok());
// panic!("{:?}", traced.render().to_vec());D // panic!("{:?}", traced.render().to_vec());
} }
} }

View File

@ -1,11 +1,11 @@
use crate::func::*; use crate::func::*;
pub trait Effect { pub trait Effect {
fn pure() -> Self; fn e_pure() -> Self;
fn seq(lhs: Self, rhs: Self) -> Self; fn e_seq(lhs: Self, rhs: Self) -> Self;
fn after(self, effect: Self) -> Self; fn e_after(self, effect: Self) -> Self;
} }
#[derive(Clone)] #[derive(Clone)]
@ -15,10 +15,10 @@ pub struct WithEffect<A, E> {
} }
impl<A, E: Effect> WithEffect<A, E> { impl<A, E: Effect> WithEffect<A, E> {
fn after(self, effect: E) -> Self { fn e_after(self, effect: E) -> Self {
WithEffect { WithEffect {
value: self.value, value: self.value,
effect: self.effect.after(effect), effect: self.effect.e_after(effect),
} }
} }
} }
@ -62,7 +62,7 @@ impl<E: Effect> Pure for EffectClass<E> {
{ {
WithEffect { WithEffect {
value: a, value: a,
effect: E::pure(), effect: E::e_pure(),
} }
} }
} }
@ -77,7 +77,7 @@ impl<E: Effect> ApplicativeSeq for EffectClass<E> {
{ {
WithEffect { WithEffect {
value: (ff.value)(fa.value), value: (ff.value)(fa.value),
effect: E::seq(ff.effect, fa.effect), effect: E::e_seq(ff.effect, fa.effect),
} }
} }
} }
@ -93,7 +93,7 @@ impl<E: Effect> ApplicativeLA2 for EffectClass<E> {
{ {
WithEffect { WithEffect {
value: f(fa.value, fb.value), value: f(fa.value, fb.value),
effect: E::seq(fa.effect, fb.effect), effect: E::e_seq(fa.effect, fb.effect),
} }
} }
} }
@ -105,7 +105,7 @@ impl<E: Effect> ApplicativeTuple for EffectClass<E> {
{ {
WithEffect { WithEffect {
value: (fa.value, fb.value), value: (fa.value, fb.value),
effect: E::seq(fa.effect, fb.effect), effect: E::e_seq(fa.effect, fb.effect),
} }
} }
} }
@ -118,7 +118,7 @@ impl<E: Effect> Applicative for EffectClass<E> {
drop(fa.value); drop(fa.value);
WithEffect { WithEffect {
value: fb.value, value: fb.value,
effect: E::seq(fa.effect, fb.effect), effect: E::e_seq(fa.effect, fb.effect),
} }
} }
@ -129,7 +129,7 @@ impl<E: Effect> Applicative for EffectClass<E> {
drop(fb.value); drop(fb.value);
WithEffect { WithEffect {
value: fa.value, value: fa.value,
effect: E::seq(fa.effect, fb.effect), effect: E::e_seq(fa.effect, fb.effect),
} }
} }
} }
@ -142,17 +142,17 @@ impl<E: Effect> Monad for EffectClass<E> {
where where
Self: 'a, Self: 'a,
{ {
f(fa.value).after(fa.effect) f(fa.value).e_after(fa.effect)
} }
fn iterate<'a, B: 'a>(mut f: impl Iterative<'a, T = Self, B = B>) -> Self::F<'a, B> fn iterate<'a, B: 'a>(mut f: impl Iterative<'a, T = Self, B = B>) -> Self::F<'a, B>
where where
Self: 'a, Self: 'a,
{ {
let mut effect = E::pure(); let mut effect = E::e_pure();
loop { loop {
let fa = f.next(); let fa = f.next();
effect = fa.effect.after(effect); effect = fa.effect.e_after(effect);
match fa.value { match fa.value {
ControlFlow::Continue(next_f) => f = next_f, ControlFlow::Continue(next_f) => f = next_f,
ControlFlow::Break(b) => return WithEffect { value: b, effect }, ControlFlow::Break(b) => return WithEffect { value: b, effect },
@ -165,7 +165,7 @@ impl<E: Effect> Monad for EffectClass<E> {
Self::F<'a, A>: 'a, Self::F<'a, A>: 'a,
Self: 'a, Self: 'a,
{ {
ffa.value.after(ffa.effect) ffa.value.e_after(ffa.effect)
} }
} }

View File

@ -272,12 +272,12 @@ mod tests {
let traced = stack.clone().vec(); let traced = stack.clone().vec();
assert_eq!(traced.length(), 0); assert_eq!(traced.length(), 0);
assert_eq!(traced.width(), 0); assert_eq!(traced.width(), 0);
assert_eq!(format!("{}", traced.t), "."); assert_eq!(format!("{}", traced.effect), ".");
let stack: T<TestContextTraced> = Rc::new(stack).trace()?; let stack: T<TestContextTraced> = Rc::new(stack).trace()?;
let traced = stack.clone().vec(); let traced = stack.clone().vec();
assert_eq!(traced.length(), 3); assert_eq!(traced.length(), 3);
assert_eq!(traced.width(), 1); assert_eq!(traced.width(), 1);
assert_eq!(format!("{}", traced.t), "( ? > ? > ? )"); assert_eq!(format!("{}", traced.effect), "( ? > ? > ? )");
Ok(()) Ok(())
} }

View File

@ -22,8 +22,21 @@ pub use self::traced::*;
pub struct TracedDiagnostic; pub struct TracedDiagnostic;
/// Implementation of [`Monad`] for [Traced] objects. /// Implementation of [`Monad`] for [Traced] objects.
#[derive(CovariantFunctor)] pub type TracedClass = classes::effect::EffectClass<TraceBox>;
pub struct TracedClass;
impl classes::effect::Effect for TraceBox {
fn e_pure() -> Self {
TraceBox::pure()
}
fn e_seq(lhs: Self, rhs: Self) -> Self {
TraceBox::parallel(lhs, rhs)
}
fn e_after(self, effect: Self) -> Self {
self.after(effect)
}
}
trait WithTrace: Sized { trait WithTrace: Sized {
fn with_trace(self, t: TraceBox) -> Traced<Self>; fn with_trace(self, t: TraceBox) -> Traced<Self>;
@ -31,15 +44,18 @@ trait WithTrace: Sized {
impl<A> WithTrace for A { impl<A> WithTrace for A {
fn with_trace(self, t: TraceBox) -> Traced<Self> { fn with_trace(self, t: TraceBox) -> Traced<Self> {
Traced { a: self, t } Traced {
value: self,
effect: t,
}
} }
} }
impl<A> Traced<A> { impl<A> Traced<A> {
fn wrapped(self, event: &str) -> Self { fn wrapped(self, event: &str) -> Self {
Traced { Traced {
a: self.a, value: self.value,
t: self.t.wrapped(event), effect: self.effect.wrapped(event),
} }
} }
@ -49,178 +65,24 @@ impl<A> Traced<A> {
fn after(self, t: TraceBox) -> Self { fn after(self, t: TraceBox) -> Self {
Traced { Traced {
a: self.a, value: self.value,
t: self.t.after(t), effect: self.effect.after(t),
} }
} }
fn before(self, t: TraceBox) -> Self { fn before(self, t: TraceBox) -> Self {
Traced { Traced {
a: self.a, value: self.value,
t: self.t.before(t), effect: self.effect.before(t),
} }
} }
pub fn length(&self) -> usize { pub fn length(&self) -> usize {
self.t.length() self.effect.length()
} }
pub fn width(&self) -> usize { pub fn width(&self) -> usize {
self.t.width() self.effect.width()
}
}
impl WeakFunctor for TracedClass {
type F<'a, A: 'a> = Traced<A>;
}
impl Functor for TracedClass {
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,
{
f(fa.a).with_trace(fa.t)
}
fn replace<'a, A: 'a, B: 'a>(fa: Self::F<'a, A>, b: B) -> Self::F<'a, B>
where
Self: 'a,
{
b.with_trace(fa.t)
}
fn void<'a, A: 'a>(fa: Self::F<'a, A>) -> Self::F<'a, ()>
where
Self: 'a,
{
().with_trace(fa.t)
}
}
impl Pure for TracedClass {
fn pure<'a, A: 'a>(a: A) -> Self::F<'a, A> {
a.with_trace(TraceBox::pure())
}
}
impl ApplicativeSeq for TracedClass {
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>
where
Self: 'a,
{
(ff.a)(fa.a).with_trace(TraceBox::parallel(ff.t, fa.t))
}
}
impl ApplicativeLA2 for TracedClass {
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>
where
Self: 'a,
{
f(fa.a, fb.a).with_trace(TraceBox::parallel(fa.t, fb.t))
}
}
impl ApplicativeTuple for TracedClass {
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,
{
(fa.a, fb.a).with_trace(TraceBox::parallel(fa.t, fb.t))
}
}
impl Applicative for TracedClass {
fn discard_first<'a, A: 'a, B: 'a>(fa: Self::F<'a, A>, fb: Self::F<'a, B>) -> Self::F<'a, B>
where
Self: 'a,
{
fb.a.with_trace(TraceBox::parallel(fa.t, fb.t))
}
fn discard_second<'a, A: 'a, B: 'a>(fa: Self::F<'a, A>, fb: Self::F<'a, B>) -> Self::F<'a, A>
where
Self: 'a,
{
fa.a.with_trace(TraceBox::parallel(fa.t, fb.t))
}
}
impl Monad for TracedClass {
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>
where
Self: 'a,
{
f(fa.a).after(fa.t)
}
fn iterate_mut<'a, A: 'a, B: 'a>(
mut a: A,
mut f: impl 'a + FnMut(A) -> Self::F<'a, ControlFlow<B, A>>,
) -> Self::F<'a, B>
where
Self: 'a,
{
let mut t = TraceBox::pure();
loop {
let fa = f(a);
t = fa.t.after(t);
match fa.a {
ControlFlow::Continue(next_a) => a = next_a,
ControlFlow::Break(b) => return b.with_trace(t),
}
}
}
fn iterate_argument<'a, A: 'a, B: 'a>(
mut a: A,
mut f: impl AIterative<'a, T = Self, A = A, B = B>,
) -> Self::F<'a, B>
where
Self: 'a,
{
let mut t = TraceBox::pure();
loop {
let fa = f.next(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 iterate<'a, B: 'a>(mut f: impl Iterative<'a, T = Self, B = B>) -> Self::F<'a, B>
where
Self: 'a,
{
let mut t = TraceBox::pure();
loop {
let fa = f.next();
t = fa.t.after(t);
match fa.a {
ControlFlow::Continue(next_f) => f = 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>
where
Self::F<'a, A>: 'a,
Self: 'a,
{
ffa.a.after(ffa.t)
} }
} }

View File

@ -40,7 +40,7 @@ impl Trace {
impl<A> Traced<A> { impl<A> Traced<A> {
pub fn render(&self) -> WithLengthAndWidth<RenderedAny> { pub fn render(&self) -> WithLengthAndWidth<RenderedAny> {
self.t.trace.render() self.effect.trace.render()
} }
} }

View File

@ -3,7 +3,4 @@ use super::*;
/// Wrapper containing the value and the corresponding execution trace. /// Wrapper containing the value and the corresponding execution trace.
/// ///
/// For what the trace contains, see its rendered form, [`RenderedAny`]. /// For what the trace contains, see its rendered form, [`RenderedAny`].
pub struct Traced<A> { pub type Traced<A> = classes::effect::WithEffect<A, TraceBox>;
pub a: A,
pub t: TraceBox,
}

View File

@ -25,15 +25,15 @@ impl Context for TestContextCounted {
pub type CountedClass = classes::effect::EffectClass<usize>; pub type CountedClass = classes::effect::EffectClass<usize>;
impl classes::effect::Effect for usize { impl classes::effect::Effect for usize {
fn pure() -> Self { fn e_pure() -> Self {
0 0
} }
fn seq(lhs: Self, rhs: Self) -> Self { fn e_seq(lhs: Self, rhs: Self) -> Self {
max(lhs, rhs) max(lhs, rhs)
} }
fn after(self, effect: Self) -> Self { fn e_after(self, effect: Self) -> Self {
self + effect self + effect
} }
} }