use crate::{Functor, HKT, NaturalIso, Satisfies};
pub fn assert_natural_iso_round_trip<W, F, G, T>(fa: F::Type<T>, ga: G::Type<T>)
where
W: NaturalIso<F, G>,
F: HKT,
G: HKT,
T: Satisfies<F::Constraint> + Satisfies<G::Constraint>,
F::Type<T>: Clone + PartialEq + core::fmt::Debug,
G::Type<T>: Clone + PartialEq + core::fmt::Debug,
{
let g_from_f: G::Type<T> = W::to_target(fa.clone());
let fa_back: F::Type<T> = W::to_source(g_from_f);
assert_eq!(
fa, fa_back,
"NaturalIso round-trip F -> G -> F failed: original {:?} differs from to_source(to_target(original))",
fa
);
let f_from_g: F::Type<T> = W::to_source(ga.clone());
let ga_back: G::Type<T> = W::to_target(f_from_g);
assert_eq!(
ga, ga_back,
"NaturalIso round-trip G -> F -> G failed: original {:?} differs from to_target(to_source(original))",
ga
);
}
pub fn assert_natural_iso_naturality<W, F, G, A, B, Func>(fa: F::Type<A>, h: Func)
where
W: NaturalIso<F, G>,
F: HKT + Functor<F>,
G: HKT + Functor<G>,
A: Satisfies<F::Constraint> + Satisfies<G::Constraint>,
B: Satisfies<F::Constraint> + Satisfies<G::Constraint>,
F::Type<A>: Clone,
G::Type<B>: PartialEq + core::fmt::Debug,
Func: FnMut(A) -> B + Clone,
{
let lhs: G::Type<B> = W::to_target(<F as Functor<F>>::fmap(fa.clone(), h.clone()));
let rhs: G::Type<B> = <G as Functor<G>>::fmap(W::to_target(fa), h);
assert_eq!(
lhs, rhs,
"NaturalIso naturality failed: to_target(F::fmap(fa, h)) != G::fmap(to_target(fa), h)"
);
}