use super::tests::*; use super::*; pub trait FunctorTestSuite<'a>: WeakFunctor<'a> + Eqr<'a> { fn sample Self::F)>(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::(|| pa(2)); }); T::sample(|pa| { res += fmap_respects_composition::(|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::sample(|pa| { res += seq_respects_identity::(|| pa(2)); }); T::sample(|pa| { T::sample(|pg| { T::sample(|pf| { res += seq_respects_composition::( || pf(|x| x + 5), || pg(|x| x + 3), || pa(2), ); }) }) }); res += seq_is_homomorphic::(|x| x + 3, || 2); T::sample(|pf| { res += seq_respects_interchange::(|| pf(|x| x + 3), || 2); }); T::sample(|pa| { T::sample(|pf| { res += seq_can_be_expressed_via_la2::(|| pf(|x| x + 3), || pa(2)); }) }); T::sample(|pa| { res += fmap_can_be_expressed_via_seq::(|x| x + 3, || pa(2)); }); T::sample(|pa| { T::sample(|pb| { res += discard_can_be_expressed_via_seq_or_la2::(|| pa(2), || pb(2)); }) }); res } pub fn monad_follows_laws<'a, T: Monad<'a> + FunctorTestSuite<'a>>() -> R { let mut res = applicative_follows_laws::(); T::sample(|pa| { res += bind_respects_left_identity::(|x| pa(x + 3), || 2); }); T::sample(|pa| { res += bind_respects_right_identity::(|| pa(2)); }); T::sample(|pa| { T::sample(|pg| { T::sample(|pf| { res += bind_is_associative::(|x| pf(x + 5), |x| pg(x + 3), || pa(2)); }) }) }); T::sample(|pa| { T::sample(|pf| { seq_can_be_expressed_via_bind::(|| pf(|x| x + 3), || pa(2)); }) }); T::sample(|pa| { res += fmap_can_be_expressed_via_bind::(|x| x + 3, || pa(2)); }); res }