use super::*;
pub type FunExtAppEq<F, G, A, X> = Comp<Lam<Ty<A, X>, Eq<App<F, A>, App<G, A>>>, Comp<Snd, Snd>>;
pub type FunExtTy<F, G, X, Y, A> = DepFunTy<
Tup3<F, G, A>, Tup3<Pow<Y, X>, Pow<Y, X>, X>,
FunExtAppEq<F, G, A, X>,
>;
#[derive(Copy, Clone)]
pub struct FFunExt(());
pub type FunExt<F, G> = App<FFunExt, Tup<F, G>>;
pub fn fun_ext_ty<F: Prop, G: Prop, X: Prop, Y: Prop, A: Prop>() ->
Ty<FunExt<F, G>, Pow<FunExtTy<F, G, X, Y, A>, Tauto<Eq<F, G>>>>
{unimplemented!()}
pub fn qu_inv_fun_ext<F: Prop, G: Prop>() -> Qu<Inv<FunExt<F, G>>> {unimplemented!()}
pub fn fun_ext_app_eq_from_eq<F: Prop, G: Prop, A: Prop, X: Prop>(
ty_a: Ty<A, X>,
eq: Eq<F, G>
) -> App<FunExtAppEq<F, G, A, X>, Tup3<F, G, A>> {
let x = app_map_eq(comp_eq_left(lam_eq_lift(ty_a.clone(),
(True.map_any(), app_map_eq(eq).map_any()))));
let x = eq::transitivity(x, eq::symmetry(eq_app_comp()));
let x = eq::transitivity(x, app_eq(eq::symmetry(eq_app_comp())));
let x = eq::transitivity(eq::transitivity(x, app_eq(app_eq(snd_def()))), app_eq(snd_def()));
eq::transitivity(x, eq::transitivity(lam(ty_a), subst_nop())).1(True)
}
pub fn fun_ext<F: Prop, G: Prop, X: Prop, Y: Prop, A: Prop>(
tauto_eq_fg: Tauto<Eq<F, G>>
) -> FunExtTy<F, G, X, Y, A> {
use hooo::{hooo_eq, hooo_imply, pow_eq_right, pow_transitivity, tauto_eq_symmetry, tr};
fn h<A: Prop, B: Prop, C: Prop, X: Prop>(ty_a: Ty<A, X>) ->
Imply<Eq<B, C>, Eq<Lam<Ty<A, X>, B>, Lam<Ty<A, X>, C>>>
{Rc::new(move |x| lam_eq_lift(ty_a.clone(), x))}
let x = hooo_imply(h)(hooo::tr().trans(tauto_eq_fg.trans(app_map_eq).trans(eq::eq_right)))
.trans(comp_eq_left).trans(app_map_eq);
let y = {
let x = tauto_eq_symmetry(tauto_eq_fg).trans(tup3_eq_snd);
eq::transitivity(hooo_eq(tr().trans(x.trans(app_eq))), pow_eq_right(x.trans(ty::eq_left)))
};
eq::in_left_arg(hooo_eq(pow_transitivity(tup3_trd, x)), y).0(fun_ext_refl())
}
pub fn fun_rev_ext<F: Prop, G: Prop, X: Prop, Y: Prop, A: Prop>(
x: FunExtTy<F, G, X, Y, A>
) -> Tauto<Eq<F, G>> {path_inv(app_theory(), qu_inv_fun_ext(), fun_ext_ty(), fun_ext)(x)}
pub fn fun_ext_app_eq_refl<F: Prop, A: Prop, X: Prop>(
ty_a: Ty<A, X>
) -> App<FunExtAppEq<F, F, A, X>, Tup3<F, F, A>> {fun_ext_app_eq_from_eq(ty_a, eq::refl())}
pub fn fun_ext_refl<F: Prop, X: Prop, Y: Prop, A: Prop>() -> FunExtTy<F, F, X, Y, A> {
hooo::pow_transitivity(tup3_trd, fun_ext_app_eq_refl)
}
pub fn fun_ext_symmetry<F: Prop, G: Prop, X: Prop, Y: Prop, A: Prop>(
x: FunExtTy<F, G, X, Y, A>
) -> FunExtTy<G, F, X, Y, A> {fun_ext(hooo::tauto_eq_symmetry(fun_rev_ext(x)))}
pub fn fun_ext_transitivity<F: Prop, G: Prop, H: Prop, X: Prop, Y: Prop, A: Prop>(
fun_ext_fg: FunExtTy<F, G, X, Y, A>,
fun_ext_gh: FunExtTy<G, H, X, Y, A>,
) -> FunExtTy<F, H, X, Y, A> {
let fg = fun_rev_ext(fun_ext_fg);
let gh = fun_rev_ext(fun_ext_gh);
fun_ext(hooo::tauto_eq_transitivity(fg, gh))
}