use super::*;
pub type DepFunTy<A, X, PredP> = Pow<App<PredP, A>, Ty<A, X>>;
pub type DepFun<F, A, X, PredP> = Ty<F, DepFunTy<A, X, PredP>>;
pub type DepLamTy<A, X, PredP> = Imply<Ty<A, X>, App<PredP, X>>;
pub type DepLam<F, A, X, PredP> = Ty<F, DepLamTy<A, X, PredP>>;
pub type DepTupTy<A, X, PredP> = Tup<Ty<A, X>, App<PredP, A>>;
pub type DepTup<A, X, B, PredP> = Ty<Tup<A, B>, DepTupTy<A, X, PredP>>;
pub fn dep_fun_pord<A: Prop, B: Prop, X: Prop, Y: Prop>(
_: POrdProof<A, X>,
_: Pow<POrdProof<B, Y>, A>
) -> POrdProof<Pow<B, A>, Pow<Y, X>> {unimplemented!()}
pub fn dep_fun_ty<A: Prop, B: Prop, X: Prop, Y: Prop>(
_ty_a: Ty<A, X>,
_ty_b: Pow<Ty<B, Y>, A>
) -> Ty<Pow<B, A>, Pow<Y, X>> {unimplemented!()}
pub fn dep_tup_pord<A: Prop, B: Prop, X: Prop, Y: Prop>(
_: POrdProof<A, X>,
_: Pow<POrdProof<B, Y>, A>
) -> POrdProof<Tup<A, B>, Tup<X, Y>> {unimplemented!()}
pub fn dep_tup_ty<A: Prop, B: Prop, X: Prop, Y: Prop>(
_ty_a: Ty<A, X>,
_ty_b: Pow<Ty<B, Y>, A>
) -> Ty<Tup<A, B>, Tup<X, Y>> {unimplemented!()}
pub fn dep_app<F: Prop, X: Prop, A: Prop, B: Prop>(
_: Pow<App<F, A>, Ty<A, X>>
) -> Pow<App<F, B>, Ty<B, X>> {unimplemented!()}
pub fn dep_fun_app<F: Prop, A: Prop, B: Prop>(_: App<Pow<App<F, A>, A>, B>) -> App<F, B> {
unimplemented!()
}
fn dep_fun_swap_app_ty<F: Prop, A: Prop, B: Prop, X: Prop, Y: Prop>(
x: Ty<F, Pow<App<Y, A>, Ty<A, X>>>
) -> Ty<F, Pow<App<Y, B>, Ty<B, X>>> {
unsafe {ty::in_right_arg(x, (Rc::new(dep_app), Rc::new(dep_app)))}
}
pub fn dep_fun_ty_formation<A: Prop, X: Prop, P: Prop>(
ty_x: Tauto<Ty<X, Type<Z>>>,
pow_ty_pa_ty_a: Pow<Ty<App<P, A>, Type<Z>>, Ty<A, X>>
) -> Tauto<Ty<DepFunTy<A, X, P>, Type<Z>>> {
use hooo::{pow_lift, hooo_rev_and};
fn f<A: Prop, B: Prop, X: Prop, Y: Prop>((x, y): And<Ty<A, X>, Pow<Ty<B, Y>, A>>) ->
Ty<Pow<B, A>, Pow<Y, X>> {dep_fun_ty(x, y)}
fn g<A: Prop, B: Prop>(x: Ty<Pow<B, A>, Pow<Type<Z>, Type<Z>>>) -> Ty<Pow<B, A>, Type<Z>> {
ty::transitivity(x, fun_type_ty())
}
hooo_rev_and((ty_x.trans(judgement_ty), pow_lift(pow_ty_pa_ty_a))).trans(f).trans(g)
}
pub fn dep_fun_intro<A: Prop, B: Prop, X: Prop, Y: Prop, P: Prop>(
x: Pow<Ty<App<P, A>, App<Y, A>>, Ty<A, X>>
) -> Tauto<DepFun<Pow<App<P, A>, A>, A, X, Y>> {
use hooo::{pow_transitivity, tauto_hooo_ty};
let f = |x| unsafe {ty::lower(x)};
tauto_hooo_ty(pow_transitivity(f, x)).trans(dep_fun_swap_app_ty)
}
pub fn dep_fun_elim<F: Prop, X: Prop, P: Prop, A: Prop, B: Prop>(
ty_f: Tauto<DepFun<F, A, X, P>>,
ty_b: Tauto<Ty<B, X>>
) -> Tauto<Ty<App<F, B>, App<P, B>>> {
use hooo::hooo_rev_and;
fn g<F: Prop, A: Prop, X: Prop, Y: Prop>(
(f, x): And<Ty<F, Pow<Y, Ty<A, X>>>, Ty<A, X>>
) -> Ty<App<F, A>, Y> {app_fun_ty(f, unsafe {ty::lift(x)})}
let x: Tauto<Ty<F, Pow<App<P, B>, Ty<B, X>>>> = ty_f.trans(dep_fun_swap_app_ty);
hooo_rev_and((x, ty_b)).trans(g::<F, B, X, App<P, B>>)
}
pub fn dep_tup_ty_formation<A: Prop, X: Prop, P: Prop>(
ty_x: Tauto<Ty<X, Type<Z>>>,
pow_ty_pa_ty_a: Pow<Ty<App<P, A>, Type<Z>>, Ty<A, X>>
) -> Tauto<Ty<DepTupTy<A, X, P>, Type<Z>>> {
use hooo::{pow_lift, hooo_rev_and};
fn f<A: Prop, B: Prop, X: Prop, Y: Prop>((x, y): And<Ty<A, X>, Pow<Ty<B, Y>, A>>) ->
Ty<Tup<A, B>, Tup<X, Y>> {dep_tup_ty(x, y)}
fn g<A: Prop, B: Prop>(x: Ty<Tup<A, B>, Tup<Type<Z>, Type<Z>>>) -> Ty<Tup<A, B>, Type<Z>> {
ty::transitivity(x, tup_type_ty())
}
hooo_rev_and((ty_x.trans(judgement_ty), pow_lift(pow_ty_pa_ty_a))).trans(f).trans(g)
}
pub fn dep_tup_intro<A: Prop, X: Prop, B: Prop, P: Prop>(
ty_a: Tauto<Ty<A, X>>,
ty_b: Tauto<Ty<B, App<P, A>>>,
) -> Tauto<DepTup<A, X, B, P>> {
let f = hooo::hooo_imply(tauto!(Rc::new(move |(ty_a, ty_b)| tup_ty(ty_a, ty_b))));
let x = hooo::hooo_rev_and((ty_a.trans(|x| unsafe {ty::lift(x)}), ty_b));
f(x)
}
pub fn dep_tup_elim<T: Prop, X: Prop, A: Prop, B: Prop>(
ty_t: Tauto<Ty<T, Tup<Ty<X, A>, App<B, X>>>>
) -> And<Tauto<Ty<App<Fst, T>, A>>, Tauto<Ty<App<Snd, T>, App<B, App<Fst, T>>>>> {
use hooo::{tauto_eq_symmetry, tauto_in_arg};
use ty::{eq_left, eq_right, lower};
let x = ty_t.trans(fst_lower);
(tauto_in_arg(ty_t.trans(fst), tauto_eq_symmetry(x.trans(eq_left)
.trans(|x| unsafe {eq_right(x)}))).trans(|x| unsafe {lower(x)}),
tauto_in_arg(ty_t.trans(snd), tauto_eq_symmetry(x.trans(app_eq)
.trans(|x| unsafe {eq_right(x)}))))
}