use crate::{HKT2Unbound, Satisfies};
pub trait Bifunctor<F: HKT2Unbound> {
fn bimap<A, B, C, D, F1, F2>(fab: F::Type<A, B>, f1: F1, f2: F2) -> F::Type<C, D>
where
A: Satisfies<F::Constraint>,
B: Satisfies<F::Constraint>,
C: Satisfies<F::Constraint>,
D: Satisfies<F::Constraint>,
F1: FnMut(A) -> C,
F2: FnMut(B) -> D;
fn first<A, B, C, F1>(fab: F::Type<A, B>, f1: F1) -> F::Type<C, B>
where
A: Satisfies<F::Constraint>,
B: Satisfies<F::Constraint> + Clone,
C: Satisfies<F::Constraint>,
F1: FnMut(A) -> C,
{
Self::bimap(fab, f1, |b| b)
}
fn second<A, B, D, F2>(fab: F::Type<A, B>, f2: F2) -> F::Type<A, D>
where
A: Satisfies<F::Constraint> + Clone,
B: Satisfies<F::Constraint>,
D: Satisfies<F::Constraint>,
F2: FnMut(B) -> D,
{
Self::bimap(fab, |a| a, f2)
}
}