use super::*;
#[derive(Copy, Clone)]
pub struct Lam<X, Y>(X, Y);
pub fn lam_ty<A: Prop, B: Prop, X: Prop, Y: Prop>(
_ty_a: Ty<A, X>,
_ty_b: Ty<B, Y>,
) -> Ty<Lam<Ty<A, X>, B>, Imply<X, Y>> {unimplemented!()}
pub fn lam_lift<A: Prop, B: Prop, X: Prop>(ty_a: Ty<A, X>, b: B) -> Lam<Ty<A, X>, B> {Lam(ty_a, b)}
pub fn lam_eq_lift<A: Prop, X: Prop, B: Prop, C: Prop>(
_ty_a: Ty<A, X>,
_eq: Eq<B, C>
) -> Eq<Lam<Ty<A, X>, B>, Lam<Ty<A, X>, C>> {unimplemented!()}
pub fn lam<A: Prop, B: Prop, X: Prop, C: Prop>(
_ty_c: Ty<C, X>
) -> Eq<App<Lam<Ty<A, X>, B>, C>, Subst<B, A, C>> {unimplemented!()}
pub fn lam_app_ty<A: Prop, B: Prop, X: Prop, Y: Prop, C: Prop>(
ty_a: Ty<A, X>,
ty_b: Ty<B, Y>,
ty_c: Ty<C, X>,
) -> Ty<App<Lam<Ty<A, X>, B>, C>, Y> {
let ty_lam: Ty<Lam<Ty<A, X>, B>, Imply<X, Y>> = lam_ty(ty_a, ty_b);
let app_lam_ty: Ty<App<_, _>, Y> = app_lam_ty(ty_lam, ty_c);
app_lam_ty
}
pub fn lam_app_ty_trivial<A: Prop, B: Prop, X: Prop>(
ty_b: Ty<B, X>,
b_is_const: IsConst<B>,
) -> Ty<App<Lam<Ty<A, X>, B>, B>, X> {
ty::eq_left(lam_app_trivial(ty_b.clone(), b_is_const)).1(ty_b)
}
pub fn lam_app_trivial<A: Prop, B: Prop, X: Prop>(
ty_b: Ty<B, X>,
b_is_const: IsConst<B>
) -> Eq<App<Lam<Ty<A, X>, B>, B>, B> {
eq::transitivity(lam(ty_b), subst_const(b_is_const))
}
pub fn lam_app_nop<A: Prop, B: Prop, X: Prop>(ty_a: Ty<A, X>) -> Eq<App<Lam<Ty<A, X>, B>, A>, B> {
eq::transitivity(lam(ty_a), subst_nop())
}
pub type LamId<A, X> = Lam<Ty<A, X>, A>;
pub fn lam_id_eq<A: Prop, X: Prop>() -> Eq<LamId<A, X>, App<FId, X>> {unimplemented!()}
pub fn lam_id_q<A: Prop, X: Prop>() -> Q<LamId<A, X>, App<FId, X>> {
hooo::q_in_left_arg(quality::right(id_q()), hooo::tauto_eq_symmetry(tauto!(lam_id_eq())))
}
pub fn lam_id_ty<A: Prop, X: Prop>(ty_a: Ty<A, X>) -> Ty<LamId<A, X>, Imply<X, X>> {
lam_ty(ty_a.clone(), ty_a)
}
pub fn lam_id_app_ty<A: Prop, B: Prop, X: Prop>(
ty_a: Ty<A, X>,
ty_b: Ty<B, X>,
) -> Ty<App<LamId<A, X>, B>, X> {
app_lam_ty(lam_id_ty(ty_a), ty_b)
}
pub fn lam_id<A: Prop, B: Prop, X: Prop, N: Nat>(
ty_x: Ty<X, Type<N>>,
ty_b: Ty<B, X>
) -> Eq<App<LamId<A, X>, B>, B> {
eq::transitivity(app_map_eq(quality::to_eq(lam_id_q())), id_def(ty_x, ty_b))
}
pub type LamFst<A, X, B, Y> = Lam<Ty<A, X>, Lam<Ty<B, Y>, A>>;
pub fn lam_fst_ty<A: Prop, X: Prop, B: Prop, Y: Prop>(
ty_a: Ty<A, X>,
ty_b: Ty<B, Y>,
) -> Ty<LamFst<A, X, B, Y>, Imply<X, Imply<Y, X>>> {
lam_ty(ty_a.clone(), lam_ty(ty_b, ty_a))
}
pub fn lam_fst<A: Prop, X: Prop, B: Prop, Y: Prop, C: Prop>(
ty_c: Ty<C, X>,
c_is_const: IsConst<C>,
) -> Eq<App<LamFst<A, X, B, Y>, C>, Lam<Ty<B, Subst<Y, A, C>>, C>> {
eq::transitivity(eq::transitivity(lam(ty_c), subst_lam()),
subst_eq_lam_body(eq::transitivity(subst_eq(subst_trivial()), subst_const(c_is_const))))
}
pub type LamSnd<A, X, B, Y> = Lam<Ty<A, X>, LamId<B, Y>>;
pub fn lam_snd_ty<A: Prop, X: Prop, B: Prop, Y: Prop>(
ty_a: Ty<A, X>,
ty_b: Ty<B, Y>
) -> Ty<LamSnd<A, X, B, Y>, Imply<X, Imply<Y, Y>>> {
lam_ty(ty_a, lam_ty(ty_b.clone(), ty_b))
}
pub fn lam_snd<A: Prop, B: Prop, C: Prop, X: Prop, Y: Prop>(
ty_c: Ty<C, X>
) -> Eq<App<LamSnd<A, X, B, Y>, C>, Lam<Ty<B, Subst<Y, A, C>>, B>> {
let x2 = subst_lam();
let b_is_const = subst_lam_const(x2.clone());
eq::transitivity(lam(ty_c), eq::transitivity(x2,
subst_eq_lam_body(eq::transitivity(subst_eq(subst_const(b_is_const.clone())),
subst_const(b_is_const)))))
}