radn-rs/src/func/test_suite.rs
2023-05-26 11:16:34 +00:00

80 lines
2.4 KiB
Rust

use super::tests::*;
use super::*;
pub trait FunctorTestSuite<'a>: WeakFunctor<'a> + Eqr<'a> {
fn sample<A: 'a, F: FnMut(&'a dyn Fn(A) -> Self::F<A>)>(f: F);
}
pub fn functor_follows_laws<'a, T: Functor<'a> + FunctorTestSuite<'a>>() -> R {
let mut res = R::default();
T::sample(|pa| {
res += fmap_respects_identity::<T, _>(|| pa(2));
});
T::sample(|pa| {
res += fmap_respects_composition::<T, _, _, _>(|x| x + 5, |x| x + 3, || pa(2));
});
res
}
pub fn applicative_follows_laws<'a, T: Applicative<'a> + FunctorTestSuite<'a>>() -> R {
let mut res = functor_follows_laws::<T>();
T::sample(|pa| {
res += seq_respects_identity::<T, _>(|| pa(2));
});
T::sample(|pa| {
T::sample(|pg| {
T::sample(|pf| {
res += seq_respects_composition::<T, _, _, _, _, _>(
|| pf(|x| x + 5),
|| pg(|x| x + 3),
|| pa(2),
);
})
})
});
res += seq_is_homomorphic::<T, _, _>(|x| x + 3, || 2);
T::sample(|pf| {
res += seq_respects_interchange::<T, _, _, _>(|| pf(|x| x + 3), || 2);
});
T::sample(|pa| {
T::sample(|pf| {
res += seq_can_be_expressed_via_la2::<T, _, _, _>(|| pf(|x| x + 3), || pa(2));
})
});
T::sample(|pa| {
res += fmap_can_be_expressed_via_seq::<T, _, _>(|x| x + 3, || pa(2));
});
T::sample(|pa| {
T::sample(|pb| {
res += discard_can_be_expressed_via_seq_or_la2::<T, _, _>(|| pa(2), || pb(2));
})
});
res
}
pub fn monad_follows_laws<'a, T: Monad<'a> + FunctorTestSuite<'a>>() -> R {
let mut res = applicative_follows_laws::<T>();
T::sample(|pa| {
res += bind_respects_left_identity::<T, _, _>(|x| pa(x + 3), || 2);
});
T::sample(|pa| {
res += bind_respects_right_identity::<T, _>(|| pa(2));
});
T::sample(|pa| {
T::sample(|pg| {
T::sample(|pf| {
res += bind_is_associative::<T, _, _, _>(|x| pf(x + 5), |x| pg(x + 3), || pa(2));
})
})
});
T::sample(|pa| {
T::sample(|pf| {
seq_can_be_expressed_via_bind::<T, _, _, _>(|| pf(|x| x + 3), || pa(2));
})
});
T::sample(|pa| {
res += fmap_can_be_expressed_via_bind::<T, _, _>(|x| x + 3, || pa(2));
});
res
}