Require Import Undecidability.SystemF.Autosubst.unscoped.
Require Import Undecidability.SystemF.SysF.

Require Import Morphisms.

Set Default Proof Using "Type".
Set Default Goal Selector "!".

Local Notation "f === g" := (fext_eq f g) (at level 80).

Section pure_term.

Lemma congr_pure_app { s0 : pure_term } { s1 : pure_term } { t0 : pure_term } { t1 : pure_term } : ( = ) ( = ) pure_app = pure_app .
Proof. congruence. Qed.

Lemma congr_pure_abs { s0 : pure_term } { t0 : pure_term } : ( = ) pure_abs = pure_abs .
Proof. congruence. Qed.

Definition upRen_pure_term_pure_term (xi : ( ) ) : ( ) :=
  up_ren .

Fixpoint ren_pure_term (xipure_term : ( ) ) (s : pure_term ) : pure_term :=
    match s return pure_term with
    | pure_var s (pure_var ) (xipure_term s)
    | pure_app pure_app (ren_pure_term xipure_term ) (ren_pure_term xipure_term )
    | pure_abs pure_abs (ren_pure_term (upRen_pure_term_pure_term xipure_term) )
    end.

Definition up_pure_term_pure_term (sigma : ( ) pure_term ) : ( ) pure_term :=
  scons ((pure_var ) var_zero) (funcomp (ren_pure_term shift) ).

Fixpoint subst_pure_term (sigmapure_term : ( ) pure_term ) (s : pure_term ) : pure_term :=
    match s return pure_term with
    | pure_var s sigmapure_term s
    | pure_app pure_app (subst_pure_term sigmapure_term ) (subst_pure_term sigmapure_term )
    | pure_abs pure_abs (subst_pure_term (up_pure_term_pure_term sigmapure_term) )
    end.

Definition upId_pure_term_pure_term (sigma : ( ) pure_term ) (Eq : x, x = (pure_var ) x) : x, (up_pure_term_pure_term ) x = (pure_var ) x :=
   n match n with
  | S n ap (ren_pure_term shift) (Eq n)
  | 0 eq_refl
  end.

Fixpoint idSubst_pure_term (sigmapure_term : ( ) pure_term ) (Eqpure_term : x, sigmapure_term x = (pure_var ) x) (s : pure_term ) : subst_pure_term sigmapure_term s = s :=
    match s return subst_pure_term sigmapure_term s = s with
    | pure_var s Eqpure_term s
    | pure_app congr_pure_app (idSubst_pure_term sigmapure_term Eqpure_term ) (idSubst_pure_term sigmapure_term Eqpure_term )
    | pure_abs congr_pure_abs (idSubst_pure_term (up_pure_term_pure_term sigmapure_term) (upId_pure_term_pure_term (_) Eqpure_term) )
    end.

Definition upExtRen_pure_term_pure_term (xi : ( ) ) (zeta : ( ) ) (Eq : x, x = x) : x, (upRen_pure_term_pure_term ) x = (upRen_pure_term_pure_term ) x :=
   n match n with
  | S n ap shift (Eq n)
  | 0 eq_refl
  end.

Fixpoint extRen_pure_term (xipure_term : ( ) ) (zetapure_term : ( ) ) (Eqpure_term : x, xipure_term x = zetapure_term x) (s : pure_term ) : ren_pure_term xipure_term s = ren_pure_term zetapure_term s :=
    match s return ren_pure_term xipure_term s = ren_pure_term zetapure_term s with
    | pure_var s ap (pure_var ) (Eqpure_term s)
    | pure_app congr_pure_app (extRen_pure_term xipure_term zetapure_term Eqpure_term ) (extRen_pure_term xipure_term zetapure_term Eqpure_term )
    | pure_abs congr_pure_abs (extRen_pure_term (upRen_pure_term_pure_term xipure_term) (upRen_pure_term_pure_term zetapure_term) (upExtRen_pure_term_pure_term (_) (_) Eqpure_term) )
    end.

Definition upExt_pure_term_pure_term (sigma : ( ) pure_term ) (tau : ( ) pure_term ) (Eq : x, x = x) : x, (up_pure_term_pure_term ) x = (up_pure_term_pure_term ) x :=
   n match n with
  | S n ap (ren_pure_term shift) (Eq n)
  | 0 eq_refl
  end.

Fixpoint ext_pure_term (sigmapure_term : ( ) pure_term ) (taupure_term : ( ) pure_term ) (Eqpure_term : x, sigmapure_term x = taupure_term x) (s : pure_term ) : subst_pure_term sigmapure_term s = subst_pure_term taupure_term s :=
    match s return subst_pure_term sigmapure_term s = subst_pure_term taupure_term s with
    | pure_var s Eqpure_term s
    | pure_app congr_pure_app (ext_pure_term sigmapure_term taupure_term Eqpure_term ) (ext_pure_term sigmapure_term taupure_term Eqpure_term )
    | pure_abs congr_pure_abs (ext_pure_term (up_pure_term_pure_term sigmapure_term) (up_pure_term_pure_term taupure_term) (upExt_pure_term_pure_term (_) (_) Eqpure_term) )
    end.

Definition up_ren_ren_pure_term_pure_term (xi : ( ) ) (tau : ( ) ) (theta : ( ) ) (Eq : x, (funcomp ) x = x) : x, (funcomp (upRen_pure_term_pure_term ) (upRen_pure_term_pure_term )) x = (upRen_pure_term_pure_term ) x :=
  up_ren_ren Eq.

Fixpoint compRenRen_pure_term (xipure_term : ( ) ) (zetapure_term : ( ) ) (rhopure_term : ( ) ) (Eqpure_term : x, (funcomp zetapure_term xipure_term) x = rhopure_term x) (s : pure_term ) : ren_pure_term zetapure_term (ren_pure_term xipure_term s) = ren_pure_term rhopure_term s :=
    match s return ren_pure_term zetapure_term (ren_pure_term xipure_term s) = ren_pure_term rhopure_term s with
    | pure_var s ap (pure_var ) (Eqpure_term s)
    | pure_app congr_pure_app (compRenRen_pure_term xipure_term zetapure_term rhopure_term Eqpure_term ) (compRenRen_pure_term xipure_term zetapure_term rhopure_term Eqpure_term )
    | pure_abs congr_pure_abs (compRenRen_pure_term (upRen_pure_term_pure_term xipure_term) (upRen_pure_term_pure_term zetapure_term) (upRen_pure_term_pure_term rhopure_term) (up_ren_ren_pure_term_pure_term (_) (_) (_) Eqpure_term) )
    end.

Definition up_ren_subst_pure_term_pure_term (xi : ( ) ) (tau : ( ) pure_term ) (theta : ( ) pure_term ) (Eq : x, (funcomp ) x = x) : x, (funcomp (up_pure_term_pure_term ) (upRen_pure_term_pure_term )) x = (up_pure_term_pure_term ) x :=
   n match n with
  | S n ap (ren_pure_term shift) (Eq n)
  | 0 eq_refl
  end.

Fixpoint compRenSubst_pure_term (xipure_term : ( ) ) (taupure_term : ( ) pure_term ) (thetapure_term : ( ) pure_term ) (Eqpure_term : x, (funcomp taupure_term xipure_term) x = thetapure_term x) (s : pure_term ) : subst_pure_term taupure_term (ren_pure_term xipure_term s) = subst_pure_term thetapure_term s :=
    match s return subst_pure_term taupure_term (ren_pure_term xipure_term s) = subst_pure_term thetapure_term s with
    | pure_var s Eqpure_term s
    | pure_app congr_pure_app (compRenSubst_pure_term xipure_term taupure_term thetapure_term Eqpure_term ) (compRenSubst_pure_term xipure_term taupure_term thetapure_term Eqpure_term )
    | pure_abs congr_pure_abs (compRenSubst_pure_term (upRen_pure_term_pure_term xipure_term) (up_pure_term_pure_term taupure_term) (up_pure_term_pure_term thetapure_term) (up_ren_subst_pure_term_pure_term (_) (_) (_) Eqpure_term) )
    end.

Definition up_subst_ren_pure_term_pure_term (sigma : ( ) pure_term ) (zetapure_term : ( ) ) (theta : ( ) pure_term ) (Eq : x, (funcomp (ren_pure_term zetapure_term) ) x = x) : x, (funcomp (ren_pure_term (upRen_pure_term_pure_term zetapure_term)) (up_pure_term_pure_term )) x = (up_pure_term_pure_term ) x :=
   n match n with
  | S n eq_trans (compRenRen_pure_term shift (upRen_pure_term_pure_term zetapure_term) (funcomp shift zetapure_term) ( x eq_refl) ( n)) (eq_trans (eq_sym (compRenRen_pure_term zetapure_term shift (funcomp shift zetapure_term) ( x eq_refl) ( n))) (ap (ren_pure_term shift) (Eq n)))
  | 0 eq_refl
  end.

Fixpoint compSubstRen_pure_term (sigmapure_term : ( ) pure_term ) (zetapure_term : ( ) ) (thetapure_term : ( ) pure_term ) (Eqpure_term : x, (funcomp (ren_pure_term zetapure_term) sigmapure_term) x = thetapure_term x) (s : pure_term ) : ren_pure_term zetapure_term (subst_pure_term sigmapure_term s) = subst_pure_term thetapure_term s :=
    match s return ren_pure_term zetapure_term (subst_pure_term sigmapure_term s) = subst_pure_term thetapure_term s with
    | pure_var s Eqpure_term s
    | pure_app congr_pure_app (compSubstRen_pure_term sigmapure_term zetapure_term thetapure_term Eqpure_term ) (compSubstRen_pure_term sigmapure_term zetapure_term thetapure_term Eqpure_term )
    | pure_abs congr_pure_abs (compSubstRen_pure_term (up_pure_term_pure_term sigmapure_term) (upRen_pure_term_pure_term zetapure_term) (up_pure_term_pure_term thetapure_term) (up_subst_ren_pure_term_pure_term (_) (_) (_) Eqpure_term) )
    end.

Definition up_subst_subst_pure_term_pure_term (sigma : ( ) pure_term ) (taupure_term : ( ) pure_term ) (theta : ( ) pure_term ) (Eq : x, (funcomp (subst_pure_term taupure_term) ) x = x) : x, (funcomp (subst_pure_term (up_pure_term_pure_term taupure_term)) (up_pure_term_pure_term )) x = (up_pure_term_pure_term ) x :=
   n match n with
  | S n eq_trans (compRenSubst_pure_term shift (up_pure_term_pure_term taupure_term) (funcomp (up_pure_term_pure_term taupure_term) shift) ( x eq_refl) ( n)) (eq_trans (eq_sym (compSubstRen_pure_term taupure_term shift (funcomp (ren_pure_term shift) taupure_term) ( x eq_refl) ( n))) (ap (ren_pure_term shift) (Eq n)))
  | 0 eq_refl
  end.

Fixpoint compSubstSubst_pure_term (sigmapure_term : ( ) pure_term ) (taupure_term : ( ) pure_term ) (thetapure_term : ( ) pure_term ) (Eqpure_term : x, (funcomp (subst_pure_term taupure_term) sigmapure_term) x = thetapure_term x) (s : pure_term ) : subst_pure_term taupure_term (subst_pure_term sigmapure_term s) = subst_pure_term thetapure_term s :=
    match s return subst_pure_term taupure_term (subst_pure_term sigmapure_term s) = subst_pure_term thetapure_term s with
    | pure_var s Eqpure_term s
    | pure_app congr_pure_app (compSubstSubst_pure_term sigmapure_term taupure_term thetapure_term Eqpure_term ) (compSubstSubst_pure_term sigmapure_term taupure_term thetapure_term Eqpure_term )
    | pure_abs congr_pure_abs (compSubstSubst_pure_term (up_pure_term_pure_term sigmapure_term) (up_pure_term_pure_term taupure_term) (up_pure_term_pure_term thetapure_term) (up_subst_subst_pure_term_pure_term (_) (_) (_) Eqpure_term) )
    end.

Definition rinstInst_up_pure_term_pure_term (xi : ( ) ) (sigma : ( ) pure_term ) (Eq : x, (funcomp (pure_var ) ) x = x) : x, (funcomp (pure_var ) (upRen_pure_term_pure_term )) x = (up_pure_term_pure_term ) x :=
   n match n with
  | S n ap (ren_pure_term shift) (Eq n)
  | 0 eq_refl
  end.

Fixpoint rinst_inst_pure_term (xipure_term : ( ) ) (sigmapure_term : ( ) pure_term ) (Eqpure_term : x, (funcomp (pure_var ) xipure_term) x = sigmapure_term x) (s : pure_term ) : ren_pure_term xipure_term s = subst_pure_term sigmapure_term s :=
    match s return ren_pure_term xipure_term s = subst_pure_term sigmapure_term s with
    | pure_var s Eqpure_term s
    | pure_app congr_pure_app (rinst_inst_pure_term xipure_term sigmapure_term Eqpure_term ) (rinst_inst_pure_term xipure_term sigmapure_term Eqpure_term )
    | pure_abs congr_pure_abs (rinst_inst_pure_term (upRen_pure_term_pure_term xipure_term) (up_pure_term_pure_term sigmapure_term) (rinstInst_up_pure_term_pure_term (_) (_) Eqpure_term) )
    end.

Lemma rinstInst_pure_term (xipure_term : ( ) ) : ren_pure_term xipure_term subst_pure_term (funcomp (pure_var ) xipure_term) .
Proof. exact (( x rinst_inst_pure_term xipure_term (_) ( n eq_refl) x)). Qed.

Lemma instId_pure_term : subst_pure_term (pure_var ) id .
Proof. exact (( x idSubst_pure_term (pure_var ) ( n eq_refl) (id x))). Qed.

Lemma feq_trans {X Y} {f g h : X Y} :
  f g g h f h.
Proof.
  cbv. congruence.
Qed.


Lemma rinstId_pure_term : @ren_pure_term id id .
Proof. exact (feq_trans (rinstInst_pure_term id) instId_pure_term). Qed.

Lemma varL_pure_term (sigmapure_term : ( ) pure_term ) : funcomp (subst_pure_term sigmapure_term) (pure_var ) sigmapure_term .
Proof. exact (( x eq_refl)). Qed.

Lemma varLRen_pure_term (xipure_term : ( ) ) : funcomp (ren_pure_term xipure_term) (pure_var ) funcomp (pure_var ) xipure_term .
Proof. exact (( x eq_refl)). Qed.

Lemma compComp_pure_term (sigmapure_term : ( ) pure_term ) (taupure_term : ( ) pure_term ) (s : pure_term ) : subst_pure_term taupure_term (subst_pure_term sigmapure_term s) = subst_pure_term (funcomp (subst_pure_term taupure_term) sigmapure_term) s .
Proof. exact (compSubstSubst_pure_term sigmapure_term taupure_term (_) ( n eq_refl) s). Qed.

Lemma compComp'_pure_term (sigmapure_term : ( ) pure_term ) (taupure_term : ( ) pure_term ) : funcomp (subst_pure_term taupure_term) (subst_pure_term sigmapure_term) subst_pure_term (funcomp (subst_pure_term taupure_term) sigmapure_term) .
Proof. exact (( n compComp_pure_term sigmapure_term taupure_term n)). Qed.

Lemma compRen_pure_term (sigmapure_term : ( ) pure_term ) (zetapure_term : ( ) ) (s : pure_term ) : ren_pure_term zetapure_term (subst_pure_term sigmapure_term s) = subst_pure_term (funcomp (ren_pure_term zetapure_term) sigmapure_term) s .
Proof. exact (compSubstRen_pure_term sigmapure_term zetapure_term (_) ( n eq_refl) s). Qed.

Lemma compRen'_pure_term (sigmapure_term : ( ) pure_term ) (zetapure_term : ( ) ) : funcomp (ren_pure_term zetapure_term) (subst_pure_term sigmapure_term) subst_pure_term (funcomp (ren_pure_term zetapure_term) sigmapure_term) .
Proof. exact (( n compRen_pure_term sigmapure_term zetapure_term n)). Qed.

Lemma renComp_pure_term (xipure_term : ( ) ) (taupure_term : ( ) pure_term ) (s : pure_term ) : subst_pure_term taupure_term (ren_pure_term xipure_term s) = subst_pure_term (funcomp taupure_term xipure_term) s .
Proof. exact (compRenSubst_pure_term xipure_term taupure_term (_) ( n eq_refl) s). Qed.

Lemma renComp'_pure_term (xipure_term : ( ) ) (taupure_term : ( ) pure_term ) : funcomp (subst_pure_term taupure_term) (ren_pure_term xipure_term) subst_pure_term (funcomp taupure_term xipure_term) .
Proof. exact (( n renComp_pure_term xipure_term taupure_term n)). Qed.

Lemma renRen_pure_term (xipure_term : ( ) ) (zetapure_term : ( ) ) (s : pure_term ) : ren_pure_term zetapure_term (ren_pure_term xipure_term s) = ren_pure_term (funcomp zetapure_term xipure_term) s .
Proof. exact (compRenRen_pure_term xipure_term zetapure_term (_) ( n eq_refl) s). Qed.

Lemma renRen'_pure_term (xipure_term : ( ) ) (zetapure_term : ( ) ) : funcomp (ren_pure_term zetapure_term) (ren_pure_term xipure_term) ren_pure_term (funcomp zetapure_term xipure_term) .
Proof. exact (( n renRen_pure_term xipure_term zetapure_term n)). Qed.

End pure_term.

Section poly_type.

Lemma congr_poly_arr { s0 : poly_type } { s1 : poly_type } { t0 : poly_type } { t1 : poly_type } : ( = ) ( = ) poly_arr = poly_arr .
Proof. congruence. Qed.

Lemma congr_poly_abs { s0 : poly_type } { t0 : poly_type } : ( = ) poly_abs = poly_abs .
Proof. congruence. Qed.

Definition upRen_poly_type_poly_type (xi : ( ) ) : ( ) :=
  up_ren .


Definition up_poly_type_poly_type (sigma : ( ) poly_type ) : ( ) poly_type :=
  scons ((poly_var ) var_zero) (funcomp (ren_poly_type shift) ).


Definition upId_poly_type_poly_type (sigma : ( ) poly_type ) (Eq : x, x = (poly_var ) x) : x, (up_poly_type_poly_type ) x = (poly_var ) x :=
   n match n with
  | S n ap (ren_poly_type shift) (Eq n)
  | 0 eq_refl
  end.

Fixpoint idSubst_poly_type (sigmapoly_type : ( ) poly_type ) (Eqpoly_type : x, sigmapoly_type x = (poly_var ) x) (s : poly_type ) : subst_poly_type sigmapoly_type s = s :=
    match s return subst_poly_type sigmapoly_type s = s with
    | poly_var s Eqpoly_type s
    | poly_arr congr_poly_arr (idSubst_poly_type sigmapoly_type Eqpoly_type ) (idSubst_poly_type sigmapoly_type Eqpoly_type )
    | poly_abs congr_poly_abs (idSubst_poly_type (up_poly_type_poly_type sigmapoly_type) (upId_poly_type_poly_type (_) Eqpoly_type) )
    end.

Definition upExtRen_poly_type_poly_type (xi : ( ) ) (zeta : ( ) ) (Eq : x, x = x) : x, (upRen_poly_type_poly_type ) x = (upRen_poly_type_poly_type ) x :=
   n match n with
  | S n ap shift (Eq n)
  | 0 eq_refl
  end.

Fixpoint extRen_poly_type (xipoly_type : ( ) ) (zetapoly_type : ( ) ) (Eqpoly_type : x, xipoly_type x = zetapoly_type x) (s : poly_type ) : ren_poly_type xipoly_type s = ren_poly_type zetapoly_type s :=
    match s return ren_poly_type xipoly_type s = ren_poly_type zetapoly_type s with
    | poly_var s ap (poly_var ) (Eqpoly_type s)
    | poly_arr congr_poly_arr (extRen_poly_type xipoly_type zetapoly_type Eqpoly_type ) (extRen_poly_type xipoly_type zetapoly_type Eqpoly_type )
    | poly_abs congr_poly_abs (extRen_poly_type (upRen_poly_type_poly_type xipoly_type) (upRen_poly_type_poly_type zetapoly_type) (upExtRen_poly_type_poly_type (_) (_) Eqpoly_type) )
    end.

Definition upExt_poly_type_poly_type (sigma : ( ) poly_type ) (tau : ( ) poly_type ) (Eq : x, x = x) : x, (up_poly_type_poly_type ) x = (up_poly_type_poly_type ) x :=
   n match n with
  | S n ap (ren_poly_type shift) (Eq n)
  | 0 eq_refl
  end.

Fixpoint ext_poly_type (sigmapoly_type : ( ) poly_type ) (taupoly_type : ( ) poly_type ) (Eqpoly_type : x, sigmapoly_type x = taupoly_type x) (s : poly_type ) : subst_poly_type sigmapoly_type s = subst_poly_type taupoly_type s :=
    match s return subst_poly_type sigmapoly_type s = subst_poly_type taupoly_type s with
    | poly_var s Eqpoly_type s
    | poly_arr congr_poly_arr (ext_poly_type sigmapoly_type taupoly_type Eqpoly_type ) (ext_poly_type sigmapoly_type taupoly_type Eqpoly_type )
    | poly_abs congr_poly_abs (ext_poly_type (up_poly_type_poly_type sigmapoly_type) (up_poly_type_poly_type taupoly_type) (upExt_poly_type_poly_type (_) (_) Eqpoly_type) )
    end.

Definition up_ren_ren_poly_type_poly_type (xi : ( ) ) (tau : ( ) ) (theta : ( ) ) (Eq : x, (funcomp ) x = x) : x, (funcomp (upRen_poly_type_poly_type ) (upRen_poly_type_poly_type )) x = (upRen_poly_type_poly_type ) x :=
  up_ren_ren Eq.

Fixpoint compRenRen_poly_type (xipoly_type : ( ) ) (zetapoly_type : ( ) ) (rhopoly_type : ( ) ) (Eqpoly_type : x, (funcomp zetapoly_type xipoly_type) x = rhopoly_type x) (s : poly_type ) : ren_poly_type zetapoly_type (ren_poly_type xipoly_type s) = ren_poly_type rhopoly_type s :=
    match s return ren_poly_type zetapoly_type (ren_poly_type xipoly_type s) = ren_poly_type rhopoly_type s with
    | poly_var s ap (poly_var ) (Eqpoly_type s)
    | poly_arr congr_poly_arr (compRenRen_poly_type xipoly_type zetapoly_type rhopoly_type Eqpoly_type ) (compRenRen_poly_type xipoly_type zetapoly_type rhopoly_type Eqpoly_type )
    | poly_abs congr_poly_abs (compRenRen_poly_type (upRen_poly_type_poly_type xipoly_type) (upRen_poly_type_poly_type zetapoly_type) (upRen_poly_type_poly_type rhopoly_type) (up_ren_ren_poly_type_poly_type (_) (_) (_) Eqpoly_type) )
    end.

Definition up_ren_subst_poly_type_poly_type (xi : ( ) ) (tau : ( ) poly_type ) (theta : ( ) poly_type ) (Eq : x, (funcomp ) x = x) : x, (funcomp (up_poly_type_poly_type ) (upRen_poly_type_poly_type )) x = (up_poly_type_poly_type ) x :=
   n match n with
  | S n ap (ren_poly_type shift) (Eq n)
  | 0 eq_refl
  end.

Fixpoint compRenSubst_poly_type (xipoly_type : ( ) ) (taupoly_type : ( ) poly_type ) (thetapoly_type : ( ) poly_type ) (Eqpoly_type : x, (funcomp taupoly_type xipoly_type) x = thetapoly_type x) (s : poly_type ) : subst_poly_type taupoly_type (ren_poly_type xipoly_type s) = subst_poly_type thetapoly_type s :=
    match s return subst_poly_type taupoly_type (ren_poly_type xipoly_type s) = subst_poly_type thetapoly_type s with
    | poly_var s Eqpoly_type s
    | poly_arr congr_poly_arr (compRenSubst_poly_type xipoly_type taupoly_type thetapoly_type Eqpoly_type ) (compRenSubst_poly_type xipoly_type taupoly_type thetapoly_type Eqpoly_type )
    | poly_abs congr_poly_abs (compRenSubst_poly_type (upRen_poly_type_poly_type xipoly_type) (up_poly_type_poly_type taupoly_type) (up_poly_type_poly_type thetapoly_type) (up_ren_subst_poly_type_poly_type (_) (_) (_) Eqpoly_type) )
    end.

Definition up_subst_ren_poly_type_poly_type (sigma : ( ) poly_type ) (zetapoly_type : ( ) ) (theta : ( ) poly_type ) (Eq : x, (funcomp (ren_poly_type zetapoly_type) ) x = x) : x, (funcomp (ren_poly_type (upRen_poly_type_poly_type zetapoly_type)) (up_poly_type_poly_type )) x = (up_poly_type_poly_type ) x :=
   n match n with
  | S n eq_trans (compRenRen_poly_type shift (upRen_poly_type_poly_type zetapoly_type) (funcomp shift zetapoly_type) ( x eq_refl) ( n)) (eq_trans (eq_sym (compRenRen_poly_type zetapoly_type shift (funcomp shift zetapoly_type) ( x eq_refl) ( n))) (ap (ren_poly_type shift) (Eq n)))
  | 0 eq_refl
  end.

Fixpoint compSubstRen_poly_type (sigmapoly_type : ( ) poly_type ) (zetapoly_type : ( ) ) (thetapoly_type : ( ) poly_type ) (Eqpoly_type : x, (funcomp (ren_poly_type zetapoly_type) sigmapoly_type) x = thetapoly_type x) (s : poly_type ) : ren_poly_type zetapoly_type (subst_poly_type sigmapoly_type s) = subst_poly_type thetapoly_type s :=
    match s return ren_poly_type zetapoly_type (subst_poly_type sigmapoly_type s) = subst_poly_type thetapoly_type s with
    | poly_var s Eqpoly_type s
    | poly_arr congr_poly_arr (compSubstRen_poly_type sigmapoly_type zetapoly_type thetapoly_type Eqpoly_type ) (compSubstRen_poly_type sigmapoly_type zetapoly_type thetapoly_type Eqpoly_type )
    | poly_abs congr_poly_abs (compSubstRen_poly_type (up_poly_type_poly_type sigmapoly_type) (upRen_poly_type_poly_type zetapoly_type) (up_poly_type_poly_type thetapoly_type) (up_subst_ren_poly_type_poly_type (_) (_) (_) Eqpoly_type) )
    end.

Definition up_subst_subst_poly_type_poly_type (sigma : ( ) poly_type ) (taupoly_type : ( ) poly_type ) (theta : ( ) poly_type ) (Eq : x, (funcomp (subst_poly_type taupoly_type) ) x = x) : x, (funcomp (subst_poly_type (up_poly_type_poly_type taupoly_type)) (up_poly_type_poly_type )) x = (up_poly_type_poly_type ) x :=
   n match n with
  | S n eq_trans (compRenSubst_poly_type shift (up_poly_type_poly_type taupoly_type) (funcomp (up_poly_type_poly_type taupoly_type) shift) ( x eq_refl) ( n)) (eq_trans (eq_sym (compSubstRen_poly_type taupoly_type shift (funcomp (ren_poly_type shift) taupoly_type) ( x eq_refl) ( n))) (ap (ren_poly_type shift) (Eq n)))
  | 0 eq_refl
  end.

Fixpoint compSubstSubst_poly_type (sigmapoly_type : ( ) poly_type ) (taupoly_type : ( ) poly_type ) (thetapoly_type : ( ) poly_type ) (Eqpoly_type : x, (funcomp (subst_poly_type taupoly_type) sigmapoly_type) x = thetapoly_type x) (s : poly_type ) : subst_poly_type taupoly_type (subst_poly_type sigmapoly_type s) = subst_poly_type thetapoly_type s :=
    match s return subst_poly_type taupoly_type (subst_poly_type sigmapoly_type s) = subst_poly_type thetapoly_type s with
    | poly_var s Eqpoly_type s
    | poly_arr congr_poly_arr (compSubstSubst_poly_type sigmapoly_type taupoly_type thetapoly_type Eqpoly_type ) (compSubstSubst_poly_type sigmapoly_type taupoly_type thetapoly_type Eqpoly_type )
    | poly_abs congr_poly_abs (compSubstSubst_poly_type (up_poly_type_poly_type sigmapoly_type) (up_poly_type_poly_type taupoly_type) (up_poly_type_poly_type thetapoly_type) (up_subst_subst_poly_type_poly_type (_) (_) (_) Eqpoly_type) )
    end.

Definition rinstInst_up_poly_type_poly_type (xi : ( ) ) (sigma : ( ) poly_type ) (Eq : x, (funcomp (poly_var ) ) x = x) : x, (funcomp (poly_var ) (upRen_poly_type_poly_type )) x = (up_poly_type_poly_type ) x :=
   n match n with
  | S n ap (ren_poly_type shift) (Eq n)
  | 0 eq_refl
  end.

Fixpoint rinst_inst_poly_type (xipoly_type : ( ) ) (sigmapoly_type : ( ) poly_type ) (Eqpoly_type : x, (funcomp (poly_var ) xipoly_type) x = sigmapoly_type x) (s : poly_type ) : ren_poly_type xipoly_type s = subst_poly_type sigmapoly_type s :=
    match s return ren_poly_type xipoly_type s = subst_poly_type sigmapoly_type s with
    | poly_var s Eqpoly_type s
    | poly_arr congr_poly_arr (rinst_inst_poly_type xipoly_type sigmapoly_type Eqpoly_type ) (rinst_inst_poly_type xipoly_type sigmapoly_type Eqpoly_type )
    | poly_abs congr_poly_abs (rinst_inst_poly_type (upRen_poly_type_poly_type xipoly_type) (up_poly_type_poly_type sigmapoly_type) (rinstInst_up_poly_type_poly_type (_) (_) Eqpoly_type) )
    end.

Lemma rinstInst_poly_type (xipoly_type : ( ) ) : ren_poly_type xipoly_type subst_poly_type (funcomp (poly_var ) xipoly_type) .
Proof. exact (( x rinst_inst_poly_type xipoly_type (_) ( n eq_refl) x)). Qed.

Lemma instId_poly_type : subst_poly_type (poly_var ) id .
Proof. exact (( x idSubst_poly_type (poly_var ) ( n eq_refl) (id x))). Qed.

Lemma rinstId_poly_type : @ren_poly_type id id .
Proof. exact (feq_trans (rinstInst_poly_type id) instId_poly_type). Qed.

Lemma varL_poly_type (sigmapoly_type : ( ) poly_type ) : funcomp (subst_poly_type sigmapoly_type) (poly_var ) sigmapoly_type .
Proof. exact (( x eq_refl)). Qed.

Lemma varLRen_poly_type (xipoly_type : ( ) ) : funcomp (ren_poly_type xipoly_type) (poly_var ) funcomp (poly_var ) xipoly_type .
Proof. exact (( x eq_refl)). Qed.

Lemma compComp_poly_type (sigmapoly_type : ( ) poly_type ) (taupoly_type : ( ) poly_type ) (s : poly_type ) : subst_poly_type taupoly_type (subst_poly_type sigmapoly_type s) = subst_poly_type (funcomp (subst_poly_type taupoly_type) sigmapoly_type) s .
Proof. exact (compSubstSubst_poly_type sigmapoly_type taupoly_type (_) ( n eq_refl) s). Qed.

Lemma compComp'_poly_type (sigmapoly_type : ( ) poly_type ) (taupoly_type : ( ) poly_type ) : funcomp (subst_poly_type taupoly_type) (subst_poly_type sigmapoly_type) subst_poly_type (funcomp (subst_poly_type taupoly_type) sigmapoly_type) .
Proof. exact (( n compComp_poly_type sigmapoly_type taupoly_type n)). Qed.

Lemma compRen_poly_type (sigmapoly_type : ( ) poly_type ) (zetapoly_type : ( ) ) (s : poly_type ) : ren_poly_type zetapoly_type (subst_poly_type sigmapoly_type s) = subst_poly_type (funcomp (ren_poly_type zetapoly_type) sigmapoly_type) s .
Proof. exact (compSubstRen_poly_type sigmapoly_type zetapoly_type (_) ( n eq_refl) s). Qed.

Lemma compRen'_poly_type (sigmapoly_type : ( ) poly_type ) (zetapoly_type : ( ) ) : funcomp (ren_poly_type zetapoly_type) (subst_poly_type sigmapoly_type) subst_poly_type (funcomp (ren_poly_type zetapoly_type) sigmapoly_type) .
Proof. exact (( n compRen_poly_type sigmapoly_type zetapoly_type n)). Qed.

Lemma renComp_poly_type (xipoly_type : ( ) ) (taupoly_type : ( ) poly_type ) (s : poly_type ) : subst_poly_type taupoly_type (ren_poly_type xipoly_type s) = subst_poly_type (funcomp taupoly_type xipoly_type) s .
Proof. exact (compRenSubst_poly_type xipoly_type taupoly_type (_) ( n eq_refl) s). Qed.

Lemma renComp'_poly_type (xipoly_type : ( ) ) (taupoly_type : ( ) poly_type ) : funcomp (subst_poly_type taupoly_type) (ren_poly_type xipoly_type) subst_poly_type (funcomp taupoly_type xipoly_type) .
Proof. exact (( n renComp_poly_type xipoly_type taupoly_type n)). Qed.

Lemma renRen_poly_type (xipoly_type : ( ) ) (zetapoly_type : ( ) ) (s : poly_type ) : ren_poly_type zetapoly_type (ren_poly_type xipoly_type s) = ren_poly_type (funcomp zetapoly_type xipoly_type) s .
Proof. exact (compRenRen_poly_type xipoly_type zetapoly_type (_) ( n eq_refl) s). Qed.

Lemma renRen'_poly_type (xipoly_type : ( ) ) (zetapoly_type : ( ) ) : funcomp (ren_poly_type zetapoly_type) (ren_poly_type xipoly_type) ren_poly_type (funcomp zetapoly_type xipoly_type) .
Proof. exact (( n renRen_poly_type xipoly_type zetapoly_type n)). Qed.

End poly_type.

Section term.

Inductive term : Type :=
  | var : term
  | app : term term term
  | abs : poly_type term term
  | ty_app : term poly_type term
  | ty_abs : term term.

Lemma congr_app { s0 : term } { s1 : term } { t0 : term } { t1 : term } : ( = ) ( = ) app = app .
Proof. congruence. Qed.

Lemma congr_abs { s0 : poly_type } { s1 : term } { t0 : poly_type } { t1 : term } : ( = ) ( = ) abs = abs .
Proof. congruence. Qed.

Lemma congr_ty_app { s0 : term } { s1 : poly_type } { t0 : term } { t1 : poly_type } : ( = ) ( = ) ty_app = ty_app .
Proof. congruence. Qed.

Lemma congr_ty_abs { s0 : term } { t0 : term } : ( = ) ty_abs = ty_abs .
Proof. congruence. Qed.

Definition upRen_poly_type_term (xi : ( ) ) : ( ) :=
  .

Definition upRen_term_poly_type (xi : ( ) ) : ( ) :=
  .

Definition upRen_term_term (xi : ( ) ) : ( ) :=
  up_ren .

Fixpoint ren_term (xipoly_type : ( ) ) (xiterm : ( ) ) (s : term ) : term :=
    match s return term with
    | var s (var ) (xiterm s)
    | app app (ren_term xipoly_type xiterm ) (ren_term xipoly_type xiterm )
    | abs abs (ren_poly_type xipoly_type ) (ren_term (upRen_term_poly_type xipoly_type) (upRen_term_term xiterm) )
    | ty_app ty_app (ren_term xipoly_type xiterm ) (ren_poly_type xipoly_type )
    | ty_abs ty_abs (ren_term (upRen_poly_type_poly_type xipoly_type) (upRen_poly_type_term xiterm) )
    end.

Definition up_poly_type_term (sigma : ( ) term ) : ( ) term :=
  funcomp (ren_term shift id) .

Definition up_term_poly_type (sigma : ( ) poly_type ) : ( ) poly_type :=
  funcomp (ren_poly_type id) .

Definition up_term_term (sigma : ( ) term ) : ( ) term :=
  scons ((var ) var_zero) (funcomp (ren_term id shift) ).

Fixpoint subst_term (sigmapoly_type : ( ) poly_type ) (sigmaterm : ( ) term ) (s : term ) : term :=
    match s return term with
    | var s sigmaterm s
    | app app (subst_term sigmapoly_type sigmaterm ) (subst_term sigmapoly_type sigmaterm )
    | abs abs (subst_poly_type sigmapoly_type ) (subst_term (up_term_poly_type sigmapoly_type) (up_term_term sigmaterm) )
    | ty_app ty_app (subst_term sigmapoly_type sigmaterm ) (subst_poly_type sigmapoly_type )
    | ty_abs ty_abs (subst_term (up_poly_type_poly_type sigmapoly_type) (up_poly_type_term sigmaterm) )
    end.

Definition upId_poly_type_term (sigma : ( ) term ) (Eq : x, x = (var ) x) : x, (up_poly_type_term ) x = (var ) x :=
   n ap (ren_term shift id) (Eq n).

Definition upId_term_poly_type (sigma : ( ) poly_type ) (Eq : x, x = (poly_var ) x) : x, (up_term_poly_type ) x = (poly_var ) x :=
   n ap (ren_poly_type id) (Eq n).

Definition upId_term_term (sigma : ( ) term ) (Eq : x, x = (var ) x) : x, (up_term_term ) x = (var ) x :=
   n match n with
  | S n ap (ren_term id shift) (Eq n)
  | 0 eq_refl
  end.

Fixpoint idSubst_term (sigmapoly_type : ( ) poly_type ) (sigmaterm : ( ) term ) (Eqpoly_type : x, sigmapoly_type x = (poly_var ) x) (Eqterm : x, sigmaterm x = (var ) x) (s : term ) : subst_term sigmapoly_type sigmaterm s = s :=
    match s return subst_term sigmapoly_type sigmaterm s = s with
    | var s Eqterm s
    | app congr_app (idSubst_term sigmapoly_type sigmaterm Eqpoly_type Eqterm ) (idSubst_term sigmapoly_type sigmaterm Eqpoly_type Eqterm )
    | abs congr_abs (idSubst_poly_type sigmapoly_type Eqpoly_type ) (idSubst_term (up_term_poly_type sigmapoly_type) (up_term_term sigmaterm) (upId_term_poly_type (_) Eqpoly_type) (upId_term_term (_) Eqterm) )
    | ty_app congr_ty_app (idSubst_term sigmapoly_type sigmaterm Eqpoly_type Eqterm ) (idSubst_poly_type sigmapoly_type Eqpoly_type )
    | ty_abs congr_ty_abs (idSubst_term (up_poly_type_poly_type sigmapoly_type) (up_poly_type_term sigmaterm) (upId_poly_type_poly_type (_) Eqpoly_type) (upId_poly_type_term (_) Eqterm) )
    end.

Definition upExtRen_poly_type_term (xi : ( ) ) (zeta : ( ) ) (Eq : x, x = x) : x, (upRen_poly_type_term ) x = (upRen_poly_type_term ) x :=
   n Eq n.

Definition upExtRen_term_poly_type (xi : ( ) ) (zeta : ( ) ) (Eq : x, x = x) : x, (upRen_term_poly_type ) x = (upRen_term_poly_type ) x :=
   n Eq n.

Definition upExtRen_term_term (xi : ( ) ) (zeta : ( ) ) (Eq : x, x = x) : x, (upRen_term_term ) x = (upRen_term_term ) x :=
   n match n with
  | S n ap shift (Eq n)
  | 0 eq_refl
  end.

Fixpoint extRen_term (xipoly_type : ( ) ) (xiterm : ( ) ) (zetapoly_type : ( ) ) (zetaterm : ( ) ) (Eqpoly_type : x, xipoly_type x = zetapoly_type x) (Eqterm : x, xiterm x = zetaterm x) (s : term ) : ren_term xipoly_type xiterm s = ren_term zetapoly_type zetaterm s :=
    match s return ren_term xipoly_type xiterm s = ren_term zetapoly_type zetaterm s with
    | var s ap (var ) (Eqterm s)
    | app congr_app (extRen_term xipoly_type xiterm zetapoly_type zetaterm Eqpoly_type Eqterm ) (extRen_term xipoly_type xiterm zetapoly_type zetaterm Eqpoly_type Eqterm )
    | abs congr_abs (extRen_poly_type xipoly_type zetapoly_type Eqpoly_type ) (extRen_term (upRen_term_poly_type xipoly_type) (upRen_term_term xiterm) (upRen_term_poly_type zetapoly_type) (upRen_term_term zetaterm) (upExtRen_term_poly_type (_) (_) Eqpoly_type) (upExtRen_term_term (_) (_) Eqterm) )
    | ty_app congr_ty_app (extRen_term xipoly_type xiterm zetapoly_type zetaterm Eqpoly_type Eqterm ) (extRen_poly_type xipoly_type zetapoly_type Eqpoly_type )
    | ty_abs congr_ty_abs (extRen_term (upRen_poly_type_poly_type xipoly_type) (upRen_poly_type_term xiterm) (upRen_poly_type_poly_type zetapoly_type) (upRen_poly_type_term zetaterm) (upExtRen_poly_type_poly_type (_) (_) Eqpoly_type) (upExtRen_poly_type_term (_) (_) Eqterm) )
    end.

Definition upExt_poly_type_term (sigma : ( ) term ) (tau : ( ) term ) (Eq : x, x = x) : x, (up_poly_type_term ) x = (up_poly_type_term ) x :=
   n ap (ren_term shift id) (Eq n).

Definition upExt_term_poly_type (sigma : ( ) poly_type ) (tau : ( ) poly_type ) (Eq : x, x = x) : x, (up_term_poly_type ) x = (up_term_poly_type ) x :=
   n ap (ren_poly_type id) (Eq n).

Definition upExt_term_term (sigma : ( ) term ) (tau : ( ) term ) (Eq : x, x = x) : x, (up_term_term ) x = (up_term_term ) x :=
   n match n with
  | S n ap (ren_term id shift) (Eq n)
  | 0 eq_refl
  end.

Fixpoint ext_term (sigmapoly_type : ( ) poly_type ) (sigmaterm : ( ) term ) (taupoly_type : ( ) poly_type ) (tauterm : ( ) term ) (Eqpoly_type : x, sigmapoly_type x = taupoly_type x) (Eqterm : x, sigmaterm x = tauterm x) (s : term ) : subst_term sigmapoly_type sigmaterm s = subst_term taupoly_type tauterm s :=
    match s return subst_term sigmapoly_type sigmaterm s = subst_term taupoly_type tauterm s with
    | var s Eqterm s
    | app congr_app (ext_term sigmapoly_type sigmaterm taupoly_type tauterm Eqpoly_type Eqterm ) (ext_term sigmapoly_type sigmaterm taupoly_type tauterm Eqpoly_type Eqterm )
    | abs congr_abs (ext_poly_type sigmapoly_type taupoly_type Eqpoly_type ) (ext_term (up_term_poly_type sigmapoly_type) (up_term_term sigmaterm) (up_term_poly_type taupoly_type) (up_term_term tauterm) (upExt_term_poly_type (_) (_) Eqpoly_type) (upExt_term_term (_) (_) Eqterm) )
    | ty_app congr_ty_app (ext_term sigmapoly_type sigmaterm taupoly_type tauterm Eqpoly_type Eqterm ) (ext_poly_type sigmapoly_type taupoly_type Eqpoly_type )
    | ty_abs congr_ty_abs (ext_term (up_poly_type_poly_type sigmapoly_type) (up_poly_type_term sigmaterm) (up_poly_type_poly_type taupoly_type) (up_poly_type_term tauterm) (upExt_poly_type_poly_type (_) (_) Eqpoly_type) (upExt_poly_type_term (_) (_) Eqterm) )
    end.

Definition up_ren_ren_poly_type_term (xi : ( ) ) (tau : ( ) ) (theta : ( ) ) (Eq : x, (funcomp ) x = x) : x, (funcomp (upRen_poly_type_term ) (upRen_poly_type_term )) x = (upRen_poly_type_term ) x.
Proof.
  intros. eapply Eq.
Qed.


Definition up_ren_ren_term_poly_type (xi : ( ) ) (tau : ( ) ) (theta : ( ) ) (Eq : x, (funcomp ) x = x) : x, (funcomp (upRen_term_poly_type ) (upRen_term_poly_type )) x = (upRen_term_poly_type ) x.
Proof.
  intros. eapply Eq.
Qed.


Definition up_ren_ren_term_term (xi : ( ) ) (tau : ( ) ) (theta : ( ) ) (Eq : x, (funcomp ) x = x) : x, (funcomp (upRen_term_term ) (upRen_term_term )) x = (upRen_term_term ) x :=
  up_ren_ren Eq.

Fixpoint compRenRen_term (xipoly_type : ( ) ) (xiterm : ( ) ) (zetapoly_type : ( ) ) (zetaterm : ( ) ) (rhopoly_type : ( ) ) (rhoterm : ( ) ) (Eqpoly_type : x, (funcomp zetapoly_type xipoly_type) x = rhopoly_type x) (Eqterm : x, (funcomp zetaterm xiterm) x = rhoterm x) (s : term ) : ren_term zetapoly_type zetaterm (ren_term xipoly_type xiterm s) = ren_term rhopoly_type rhoterm s :=
    match s return ren_term zetapoly_type zetaterm (ren_term xipoly_type xiterm s) = ren_term rhopoly_type rhoterm s with
    | var s ap (var ) (Eqterm s)
    | app congr_app (compRenRen_term xipoly_type xiterm zetapoly_type zetaterm rhopoly_type rhoterm Eqpoly_type Eqterm ) (compRenRen_term xipoly_type xiterm zetapoly_type zetaterm rhopoly_type rhoterm Eqpoly_type Eqterm )
    | abs congr_abs (compRenRen_poly_type xipoly_type zetapoly_type rhopoly_type Eqpoly_type ) (compRenRen_term (upRen_term_poly_type xipoly_type) (upRen_term_term xiterm) (upRen_term_poly_type zetapoly_type) (upRen_term_term zetaterm) (upRen_term_poly_type rhopoly_type) (upRen_term_term rhoterm) Eqpoly_type (up_ren_ren_term_term (_) (_) (_) Eqterm) )
    | ty_app congr_ty_app (compRenRen_term xipoly_type xiterm zetapoly_type zetaterm rhopoly_type rhoterm Eqpoly_type Eqterm ) (compRenRen_poly_type xipoly_type zetapoly_type rhopoly_type Eqpoly_type )
    | ty_abs congr_ty_abs (compRenRen_term (upRen_poly_type_poly_type xipoly_type) (upRen_poly_type_term xiterm) (upRen_poly_type_poly_type zetapoly_type) (upRen_poly_type_term zetaterm) (upRen_poly_type_poly_type rhopoly_type) (upRen_poly_type_term rhoterm) (up_ren_ren_poly_type_poly_type (_) (_) (_) Eqpoly_type) Eqterm )
    end.

Definition up_ren_subst_poly_type_term (xi : ( ) ) (tau : ( ) term ) (theta : ( ) term ) (Eq : x, (funcomp ) x = x) : x, (funcomp (up_poly_type_term ) (upRen_poly_type_term )) x = (up_poly_type_term ) x :=
   n ap (ren_term shift id) (Eq n).

Definition up_ren_subst_term_poly_type (xi : ( ) ) (tau : ( ) poly_type ) (theta : ( ) poly_type ) (Eq : x, (funcomp ) x = x) : x, (funcomp (up_term_poly_type ) (upRen_term_poly_type )) x = (up_term_poly_type ) x :=
   n ap (ren_poly_type id) (Eq n).

Definition up_ren_subst_term_term (xi : ( ) ) (tau : ( ) term ) (theta : ( ) term ) (Eq : x, (funcomp ) x = x) : x, (funcomp (up_term_term ) (upRen_term_term )) x = (up_term_term ) x :=
   n match n with
  | S n ap (ren_term id shift) (Eq n)
  | 0 eq_refl
  end.

Fixpoint compRenSubst_term (xipoly_type : ( ) ) (xiterm : ( ) ) (taupoly_type : ( ) poly_type ) (tauterm : ( ) term ) (thetapoly_type : ( ) poly_type ) (thetaterm : ( ) term ) (Eqpoly_type : x, (funcomp taupoly_type xipoly_type) x = thetapoly_type x) (Eqterm : x, (funcomp tauterm xiterm) x = thetaterm x) (s : term ) : subst_term taupoly_type tauterm (ren_term xipoly_type xiterm s) = subst_term thetapoly_type thetaterm s :=
    match s return subst_term taupoly_type tauterm (ren_term xipoly_type xiterm s) = subst_term thetapoly_type thetaterm s with
    | var s Eqterm s
    | app congr_app (compRenSubst_term xipoly_type xiterm taupoly_type tauterm thetapoly_type thetaterm Eqpoly_type Eqterm ) (compRenSubst_term xipoly_type xiterm taupoly_type tauterm thetapoly_type thetaterm Eqpoly_type Eqterm )
    | abs congr_abs (compRenSubst_poly_type xipoly_type taupoly_type thetapoly_type Eqpoly_type ) (compRenSubst_term (upRen_term_poly_type xipoly_type) (upRen_term_term xiterm) (up_term_poly_type taupoly_type) (up_term_term tauterm) (up_term_poly_type thetapoly_type) (up_term_term thetaterm) (up_ren_subst_term_poly_type (_) (_) (_) Eqpoly_type) (up_ren_subst_term_term (_) (_) (_) Eqterm) )
    | ty_app congr_ty_app (compRenSubst_term xipoly_type xiterm taupoly_type tauterm thetapoly_type thetaterm Eqpoly_type Eqterm ) (compRenSubst_poly_type xipoly_type taupoly_type thetapoly_type Eqpoly_type )
    | ty_abs congr_ty_abs (compRenSubst_term (upRen_poly_type_poly_type xipoly_type) (upRen_poly_type_term xiterm) (up_poly_type_poly_type taupoly_type) (up_poly_type_term tauterm) (up_poly_type_poly_type thetapoly_type) (up_poly_type_term thetaterm) (up_ren_subst_poly_type_poly_type (_) (_) (_) Eqpoly_type) (up_ren_subst_poly_type_term (_) (_) (_) Eqterm) )
    end.

Definition up_subst_ren_poly_type_term (sigma : ( ) term ) (zetapoly_type : ( ) ) (zetaterm : ( ) ) (theta : ( ) term ) (Eq : x, (funcomp (ren_term zetapoly_type zetaterm) ) x = x) : x, (funcomp (ren_term (upRen_poly_type_poly_type zetapoly_type) (upRen_poly_type_term zetaterm)) (up_poly_type_term )) x = (up_poly_type_term ) x :=
   n eq_trans (compRenRen_term shift id (upRen_poly_type_poly_type zetapoly_type) (upRen_poly_type_term zetaterm) (funcomp shift zetapoly_type) (funcomp id zetaterm) ( x eq_refl) ( x eq_refl) ( n)) (eq_trans (eq_sym (compRenRen_term zetapoly_type zetaterm shift id (funcomp shift zetapoly_type) (funcomp id zetaterm) ( x eq_refl) ( x eq_refl) ( n))) (ap (ren_term shift id) (Eq n))).

Definition up_subst_ren_term_poly_type (sigma : ( ) poly_type ) (zetapoly_type : ( ) ) (theta : ( ) poly_type ) (Eq : x, (funcomp (ren_poly_type zetapoly_type) ) x = x) : x, (funcomp (ren_poly_type (upRen_term_poly_type zetapoly_type)) (up_term_poly_type )) x = (up_term_poly_type ) x :=
   n eq_trans (compRenRen_poly_type id (upRen_term_poly_type zetapoly_type) (funcomp id zetapoly_type) ( x eq_refl) ( n)) (eq_trans (eq_sym (compRenRen_poly_type zetapoly_type id (funcomp id zetapoly_type) ( x eq_refl) ( n))) (ap (ren_poly_type id) (Eq n))).

Definition up_subst_ren_term_term (sigma : ( ) term ) (zetapoly_type : ( ) ) (zetaterm : ( ) ) (theta : ( ) term ) (Eq : x, (funcomp (ren_term zetapoly_type zetaterm) ) x = x) : x, (funcomp (ren_term (upRen_term_poly_type zetapoly_type) (upRen_term_term zetaterm)) (up_term_term )) x = (up_term_term ) x :=
   n match n with
  | S n eq_trans (compRenRen_term id shift (upRen_term_poly_type zetapoly_type) (upRen_term_term zetaterm) (funcomp id zetapoly_type) (funcomp shift zetaterm) ( x eq_refl) ( x eq_refl) ( n)) (eq_trans (eq_sym (compRenRen_term zetapoly_type zetaterm id shift (funcomp id zetapoly_type) (funcomp shift zetaterm) ( x eq_refl) ( x eq_refl) ( n))) (ap (ren_term id shift) (Eq n)))
  | 0 eq_refl
  end.

Fixpoint compSubstRen_term (sigmapoly_type : ( ) poly_type ) (sigmaterm : ( ) term ) (zetapoly_type : ( ) ) (zetaterm : ( ) ) (thetapoly_type : ( ) poly_type ) (thetaterm : ( ) term ) (Eqpoly_type : x, (funcomp (ren_poly_type zetapoly_type) sigmapoly_type) x = thetapoly_type x) (Eqterm : x, (funcomp (ren_term zetapoly_type zetaterm) sigmaterm) x = thetaterm x) (s : term ) : ren_term zetapoly_type zetaterm (subst_term sigmapoly_type sigmaterm s) = subst_term thetapoly_type thetaterm s :=
    match s return ren_term zetapoly_type zetaterm (subst_term sigmapoly_type sigmaterm s) = subst_term thetapoly_type thetaterm s with
    | var s Eqterm s
    | app congr_app (compSubstRen_term sigmapoly_type sigmaterm zetapoly_type zetaterm thetapoly_type thetaterm Eqpoly_type Eqterm ) (compSubstRen_term sigmapoly_type sigmaterm zetapoly_type zetaterm thetapoly_type thetaterm Eqpoly_type Eqterm )
    | abs congr_abs (compSubstRen_poly_type sigmapoly_type zetapoly_type thetapoly_type Eqpoly_type ) (compSubstRen_term (up_term_poly_type sigmapoly_type) (up_term_term sigmaterm) (upRen_term_poly_type zetapoly_type) (upRen_term_term zetaterm) (up_term_poly_type thetapoly_type) (up_term_term thetaterm) (up_subst_ren_term_poly_type (_) (_) (_) Eqpoly_type) (up_subst_ren_term_term (_) (_) (_) (_) Eqterm) )
    | ty_app congr_ty_app (compSubstRen_term sigmapoly_type sigmaterm zetapoly_type zetaterm thetapoly_type thetaterm Eqpoly_type Eqterm ) (compSubstRen_poly_type sigmapoly_type zetapoly_type thetapoly_type Eqpoly_type )
    | ty_abs congr_ty_abs (compSubstRen_term (up_poly_type_poly_type sigmapoly_type) (up_poly_type_term sigmaterm) (upRen_poly_type_poly_type zetapoly_type) (upRen_poly_type_term zetaterm) (up_poly_type_poly_type thetapoly_type) (up_poly_type_term thetaterm) (up_subst_ren_poly_type_poly_type (_) (_) (_) Eqpoly_type) (up_subst_ren_poly_type_term (_) (_) (_) (_) Eqterm) )
    end.

Definition up_subst_subst_poly_type_term (sigma : ( ) term ) (taupoly_type : ( ) poly_type ) (tauterm : ( ) term ) (theta : ( ) term ) (Eq : x, (funcomp (subst_term taupoly_type tauterm) ) x = x) : x, (funcomp (subst_term (up_poly_type_poly_type taupoly_type) (up_poly_type_term tauterm)) (up_poly_type_term )) x = (up_poly_type_term ) x :=
   n eq_trans (compRenSubst_term shift id (up_poly_type_poly_type taupoly_type) (up_poly_type_term tauterm) (funcomp (up_poly_type_poly_type taupoly_type) shift) (funcomp (up_poly_type_term tauterm) id) ( x eq_refl) ( x eq_refl) ( n)) (eq_trans (eq_sym (compSubstRen_term taupoly_type tauterm shift id (funcomp (ren_poly_type shift) taupoly_type) (funcomp (ren_term shift id) tauterm) ( x eq_refl) ( x eq_refl) ( n))) (ap (ren_term shift id) (Eq n))).

Definition up_subst_subst_term_poly_type (sigma : ( ) poly_type ) (taupoly_type : ( ) poly_type ) (theta : ( ) poly_type ) (Eq : x, (funcomp (subst_poly_type taupoly_type) ) x = x) : x, (funcomp (subst_poly_type (up_term_poly_type taupoly_type)) (up_term_poly_type )) x = (up_term_poly_type ) x :=
   n eq_trans (compRenSubst_poly_type id (up_term_poly_type taupoly_type) (funcomp (up_term_poly_type taupoly_type) id) ( x eq_refl) ( n)) (eq_trans (eq_sym (compSubstRen_poly_type taupoly_type id (funcomp (ren_poly_type id) taupoly_type) ( x eq_refl) ( n))) (ap (ren_poly_type id) (Eq n))).

Definition up_subst_subst_term_term (sigma : ( ) term ) (taupoly_type : ( ) poly_type ) (tauterm : ( ) term ) (theta : ( ) term ) (Eq : x, (funcomp (subst_term taupoly_type tauterm) ) x = x) : x, (funcomp (subst_term (up_term_poly_type taupoly_type) (up_term_term tauterm)) (up_term_term )) x = (up_term_term ) x :=
   n match n with
  | S n eq_trans (compRenSubst_term id shift (up_term_poly_type taupoly_type) (up_term_term tauterm) (funcomp (up_term_poly_type taupoly_type) id) (funcomp (up_term_term tauterm) shift) ( x eq_refl) ( x eq_refl) ( n)) (eq_trans (eq_sym (compSubstRen_term taupoly_type tauterm id shift (funcomp (ren_poly_type id) taupoly_type) (funcomp (ren_term id shift) tauterm) ( x eq_refl) ( x eq_refl) ( n))) (ap (ren_term id shift) (Eq n)))
  | 0 eq_refl
  end.

Fixpoint compSubstSubst_term (sigmapoly_type : ( ) poly_type ) (sigmaterm : ( ) term ) (taupoly_type : ( ) poly_type ) (tauterm : ( ) term ) (thetapoly_type : ( ) poly_type ) (thetaterm : ( ) term ) (Eqpoly_type : x, (funcomp (subst_poly_type taupoly_type) sigmapoly_type) x = thetapoly_type x) (Eqterm : x, (funcomp (subst_term taupoly_type tauterm) sigmaterm) x = thetaterm x) (s : term ) : subst_term taupoly_type tauterm (subst_term sigmapoly_type sigmaterm s) = subst_term thetapoly_type thetaterm s :=
    match s return subst_term taupoly_type tauterm (subst_term sigmapoly_type sigmaterm s) = subst_term thetapoly_type thetaterm s with
    | var s Eqterm s
    | app congr_app (compSubstSubst_term sigmapoly_type sigmaterm taupoly_type tauterm thetapoly_type thetaterm Eqpoly_type Eqterm ) (compSubstSubst_term sigmapoly_type sigmaterm taupoly_type tauterm thetapoly_type thetaterm Eqpoly_type Eqterm )
    | abs congr_abs (compSubstSubst_poly_type sigmapoly_type taupoly_type thetapoly_type Eqpoly_type ) (compSubstSubst_term (up_term_poly_type sigmapoly_type) (up_term_term sigmaterm) (up_term_poly_type taupoly_type) (up_term_term tauterm) (up_term_poly_type thetapoly_type) (up_term_term thetaterm) (up_subst_subst_term_poly_type (_) (_) (_) Eqpoly_type) (up_subst_subst_term_term (_) (_) (_) (_) Eqterm) )
    | ty_app congr_ty_app (compSubstSubst_term sigmapoly_type sigmaterm taupoly_type tauterm thetapoly_type thetaterm Eqpoly_type Eqterm ) (compSubstSubst_poly_type sigmapoly_type taupoly_type thetapoly_type Eqpoly_type )
    | ty_abs congr_ty_abs (compSubstSubst_term (up_poly_type_poly_type sigmapoly_type) (up_poly_type_term sigmaterm) (up_poly_type_poly_type taupoly_type) (up_poly_type_term tauterm) (up_poly_type_poly_type thetapoly_type) (up_poly_type_term thetaterm) (up_subst_subst_poly_type_poly_type (_) (_) (_) Eqpoly_type) (up_subst_subst_poly_type_term (_) (_) (_) (_) Eqterm) )
    end.

Definition rinstInst_up_poly_type_term (xi : ( ) ) (sigma : ( ) term ) (Eq : x, (funcomp (var ) ) x = x) : x, (funcomp (var ) (upRen_poly_type_term )) x = (up_poly_type_term ) x :=
   n ap (ren_term shift id) (Eq n).

Definition rinstInst_up_term_poly_type (xi : ( ) ) (sigma : ( ) poly_type ) (Eq : x, (funcomp (poly_var ) ) x = x) : x, (funcomp (poly_var ) (upRen_term_poly_type )) x = (up_term_poly_type ) x :=
   n ap (ren_poly_type id) (Eq n).

Definition rinstInst_up_term_term (xi : ( ) ) (sigma : ( ) term ) (Eq : x, (funcomp (var ) ) x = x) : x, (funcomp (var ) (upRen_term_term )) x = (up_term_term ) x :=
   n match n with
  | S n ap (ren_term id shift) (Eq n)
  | 0 eq_refl
  end.

Fixpoint rinst_inst_term (xipoly_type : ( ) ) (xiterm : ( ) ) (sigmapoly_type : ( ) poly_type ) (sigmaterm : ( ) term ) (Eqpoly_type : x, (funcomp (poly_var ) xipoly_type) x = sigmapoly_type x) (Eqterm : x, (funcomp (var ) xiterm) x = sigmaterm x) (s : term ) : ren_term xipoly_type xiterm s = subst_term sigmapoly_type sigmaterm s :=
    match s return ren_term xipoly_type xiterm s = subst_term sigmapoly_type sigmaterm s with
    | var s Eqterm s
    | app congr_app (rinst_inst_term xipoly_type xiterm sigmapoly_type sigmaterm Eqpoly_type Eqterm ) (rinst_inst_term xipoly_type xiterm sigmapoly_type sigmaterm Eqpoly_type Eqterm )
    | abs congr_abs (rinst_inst_poly_type xipoly_type sigmapoly_type Eqpoly_type ) (rinst_inst_term (upRen_term_poly_type xipoly_type) (upRen_term_term xiterm) (up_term_poly_type sigmapoly_type) (up_term_term sigmaterm) (rinstInst_up_term_poly_type (_) (_) Eqpoly_type) (rinstInst_up_term_term (_) (_) Eqterm) )
    | ty_app congr_ty_app (rinst_inst_term xipoly_type xiterm sigmapoly_type sigmaterm Eqpoly_type Eqterm ) (rinst_inst_poly_type xipoly_type sigmapoly_type Eqpoly_type )
    | ty_abs congr_ty_abs (rinst_inst_term (upRen_poly_type_poly_type xipoly_type) (upRen_poly_type_term xiterm) (up_poly_type_poly_type sigmapoly_type) (up_poly_type_term sigmaterm) (rinstInst_up_poly_type_poly_type (_) (_) Eqpoly_type) (rinstInst_up_poly_type_term (_) (_) Eqterm) )
    end.

Lemma rinstInst_term (xipoly_type : ( ) ) (xiterm : ( ) ) : ren_term xipoly_type xiterm subst_term (funcomp (poly_var ) xipoly_type) (funcomp (var ) xiterm) .
Proof. exact (( x rinst_inst_term xipoly_type xiterm (_) (_) ( n eq_refl) ( n eq_refl) x)). Qed.

Lemma instId_term : subst_term (poly_var ) (var ) id .
Proof. exact (( x idSubst_term (poly_var ) (var ) ( n eq_refl) ( n eq_refl) (id x))). Qed.

Lemma rinstId_term : @ren_term id id id .
Proof. exact (feq_trans (rinstInst_term id id) instId_term). Qed.

Lemma varL_term (sigmapoly_type : ( ) poly_type ) (sigmaterm : ( ) term ) : funcomp (subst_term sigmapoly_type sigmaterm) (var ) sigmaterm .
Proof. exact (( x eq_refl)). Qed.

Lemma varLRen_term (xipoly_type : ( ) ) (xiterm : ( ) ) : funcomp (ren_term xipoly_type xiterm) (var ) funcomp (var ) xiterm .
Proof. exact (( x eq_refl)). Qed.

Lemma compComp_term (sigmapoly_type : ( ) poly_type ) (sigmaterm : ( ) term ) (taupoly_type : ( ) poly_type ) (tauterm : ( ) term ) (s : term ) : subst_term taupoly_type tauterm (subst_term sigmapoly_type sigmaterm s) = subst_term (funcomp (subst_poly_type taupoly_type) sigmapoly_type) (funcomp (subst_term taupoly_type tauterm) sigmaterm) s .
Proof. exact (compSubstSubst_term sigmapoly_type sigmaterm taupoly_type tauterm (_) (_) ( n eq_refl) ( n eq_refl) s). Qed.

Lemma compComp'_term (sigmapoly_type : ( ) poly_type ) (sigmaterm : ( ) term ) (taupoly_type : ( ) poly_type ) (tauterm : ( ) term ) : funcomp (subst_term taupoly_type tauterm) (subst_term sigmapoly_type sigmaterm) subst_term (funcomp (subst_poly_type taupoly_type) sigmapoly_type) (funcomp (subst_term taupoly_type tauterm) sigmaterm) .
Proof. exact (( n compComp_term sigmapoly_type sigmaterm taupoly_type tauterm n)). Qed.

Lemma compRen_term (sigmapoly_type : ( ) poly_type ) (sigmaterm : ( ) term ) (zetapoly_type : ( ) ) (zetaterm : ( ) ) (s : term ) : ren_term zetapoly_type zetaterm (subst_term sigmapoly_type sigmaterm s) = subst_term (funcomp (ren_poly_type zetapoly_type) sigmapoly_type) (funcomp (ren_term zetapoly_type zetaterm) sigmaterm) s .
Proof. exact (compSubstRen_term sigmapoly_type sigmaterm zetapoly_type zetaterm (_) (_) ( n eq_refl) ( n eq_refl) s). Qed.

Lemma compRen'_term (sigmapoly_type : ( ) poly_type ) (sigmaterm : ( ) term ) (zetapoly_type : ( ) ) (zetaterm : ( ) ) : funcomp (ren_term zetapoly_type zetaterm) (subst_term sigmapoly_type sigmaterm) subst_term (funcomp (ren_poly_type zetapoly_type) sigmapoly_type) (funcomp (ren_term zetapoly_type zetaterm) sigmaterm) .
Proof. exact (( n compRen_term sigmapoly_type sigmaterm zetapoly_type zetaterm n)). Qed.

Lemma renComp_term (xipoly_type : ( ) ) (xiterm : ( ) ) (taupoly_type : ( ) poly_type ) (tauterm : ( ) term ) (s : term ) : subst_term taupoly_type tauterm (ren_term xipoly_type xiterm s) = subst_term (funcomp taupoly_type xipoly_type) (funcomp tauterm xiterm) s .
Proof. exact (compRenSubst_term xipoly_type xiterm taupoly_type tauterm (_) (_) ( n eq_refl) ( n eq_refl) s). Qed.

Lemma renComp'_term (xipoly_type : ( ) ) (xiterm : ( ) ) (taupoly_type : ( ) poly_type ) (tauterm : ( ) term ) : funcomp (subst_term taupoly_type tauterm) (ren_term xipoly_type xiterm) subst_term (funcomp taupoly_type xipoly_type) (funcomp tauterm xiterm) .
Proof. exact (( n renComp_term xipoly_type xiterm taupoly_type tauterm n)). Qed.

Lemma renRen_term (xipoly_type : ( ) ) (xiterm : ( ) ) (zetapoly_type : ( ) ) (zetaterm : ( ) ) (s : term ) : ren_term zetapoly_type zetaterm (ren_term xipoly_type xiterm s) = ren_term (funcomp zetapoly_type xipoly_type) (funcomp zetaterm xiterm) s .
Proof. exact (compRenRen_term xipoly_type xiterm zetapoly_type zetaterm (_) (_) ( n eq_refl) ( n eq_refl) s). Qed.

Lemma renRen'_term (xipoly_type : ( ) ) (xiterm : ( ) ) (zetapoly_type : ( ) ) (zetaterm : ( ) ) : funcomp (ren_term zetapoly_type zetaterm) (ren_term xipoly_type xiterm) ren_term (funcomp zetapoly_type xipoly_type) (funcomp zetaterm xiterm) .
Proof. exact (( n renRen_term xipoly_type xiterm zetapoly_type zetaterm n)). Qed.

End term.

#[export] Instance proper1 : Proper (fext_eq fext_eq) ren_poly_type.
Proof.
  repeat intros ?. eapply extRen_poly_type. firstorder.
Qed.


#[export] Instance proper2 : Proper (fext_eq fext_eq fext_eq) ren_term.
Proof.
  repeat intros ?. eapply extRen_term; firstorder.
Qed.


#[export] Instance proper3 : Proper (fext_eq fext_eq) subst_poly_type.
Proof.
  repeat intros ?. eapply ext_poly_type. firstorder.
Qed.


#[export] Instance proper4 : Proper (fext_eq fext_eq fext_eq) subst_term.
Proof.
  repeat intros ?. eapply ext_term; firstorder.
Qed.


Ltac asimpl' := repeat first [progress rewrite ?instId_pure_term| progress rewrite ?rinstId_pure_term| progress rewrite ?compComp_pure_term| progress rewrite ?compComp'_pure_term| progress rewrite ?compRen_pure_term| progress rewrite ?compRen'_pure_term| progress rewrite ?renComp_pure_term| progress rewrite ?renComp'_pure_term| progress rewrite ?renRen_pure_term| progress rewrite ?renRen'_pure_term| progress rewrite ?instId_poly_type| progress rewrite ?rinstId_poly_type| progress rewrite ?compComp_poly_type| progress rewrite ?compComp'_poly_type| progress rewrite ?compRen_poly_type| progress rewrite ?compRen'_poly_type| progress rewrite ?renComp_poly_type| progress rewrite ?renComp'_poly_type| progress rewrite ?renRen_poly_type| progress rewrite ?renRen'_poly_type| progress rewrite ?instId_term| progress rewrite ?rinstId_term| progress rewrite ?compComp_term| progress rewrite ?compComp'_term| progress rewrite ?compRen_term| progress rewrite ?compRen'_term| progress rewrite ?renComp_term| progress rewrite ?renComp'_term| progress rewrite ?renRen_term| progress rewrite ?renRen'_term| progress rewrite ?varL_pure_term| progress rewrite ?varLRen_pure_term| progress rewrite ?varL_poly_type| progress rewrite ?varLRen_poly_type| progress rewrite ?varL_term| progress rewrite ?varLRen_term| progress (unfold up_ren, upRen_pure_term_pure_term, upRen_poly_type_poly_type, upRen_poly_type_term, upRen_term_poly_type, upRen_term_term, up_pure_term_pure_term, up_poly_type_poly_type, up_poly_type_term, up_term_poly_type, up_term_term)| progress (cbn [subst_pure_term subst_poly_type subst_term ren_pure_term ren_poly_type ren_term])| fsimpl].

Ltac asimpl := repeat try unfold_funcomp; asimpl'; repeat try unfold_funcomp.

Tactic Notation "asimpl" "in" hyp(J) := revert J; asimpl; intros J.

Tactic Notation "asimpl" "in" "*" := repeat first [progress rewrite ?instId_pure_term in *| progress rewrite ?rinstId_pure_term in *| progress rewrite ?compComp_pure_term in *| progress rewrite ?compComp'_pure_term in *| progress rewrite ?compRen_pure_term in *| progress rewrite ?compRen'_pure_term in *| progress rewrite ?renComp_pure_term in *| progress rewrite ?renComp'_pure_term in *| progress rewrite ?renRen_pure_term in *| progress rewrite ?renRen'_pure_term in *| progress rewrite ?instId_poly_type in *| progress rewrite ?rinstId_poly_type in *| progress rewrite ?compComp_poly_type in *| progress rewrite ?compComp'_poly_type in *| progress rewrite ?compRen_poly_type in *| progress rewrite ?compRen'_poly_type in *| progress rewrite ?renComp_poly_type in *| progress rewrite ?renComp'_poly_type in *| progress rewrite ?renRen_poly_type in *| progress rewrite ?renRen'_poly_type in *| progress rewrite ?instId_term in *| progress rewrite ?rinstId_term in *| progress rewrite ?compComp_term in *| progress rewrite ?compComp'_term in *| progress rewrite ?compRen_term in *| progress rewrite ?compRen'_term in *| progress rewrite ?renComp_term in *| progress rewrite ?renComp'_term in *| progress rewrite ?renRen_term in *| progress rewrite ?renRen'_term in *| progress rewrite ?varL_pure_term in *| progress rewrite ?varLRen_pure_term in *| progress rewrite ?varL_poly_type in *| progress rewrite ?varLRen_poly_type in *| progress rewrite ?varL_term in *| progress rewrite ?varLRen_term in *| progress (unfold up_ren, upRen_pure_term_pure_term, upRen_poly_type_poly_type, upRen_poly_type_term, upRen_term_poly_type, upRen_term_term, up_pure_term_pure_term, up_poly_type_poly_type, up_poly_type_term, up_term_poly_type, up_term_term in *)| progress (cbn [subst_pure_term subst_poly_type subst_term ren_pure_term ren_poly_type ren_term] in *)| fsimpl in *].