Set Implicit Arguments.
Unset Strict Implicit.
From Coq.Relations Require Import Relation_Operators.
Require Import List.
Require Import core unscoped syntax.
Import RenNotations.
Import SubstNotations.
Import CombineNotations.
Import UnscopedNotations.
Inductive is_value : prog -> Prop :=
| iv_var x : is_value (var_prog x)
| iv_tyabs k e : is_value (tyabs k e)
| iv_tmabs t e : is_value (tmabs t e).
Inductive red_prog : prog -> prog -> Prop :=
| rp_betaty k e t t' : t' = subst_prog (t..) var_prog e -> red_prog (tyapp (tyabs k e) t) t'
| rp_betatm t e1 e2 e : e = subst_prog var_type (e2..) e1 -> is_value e2 -> red_prog (tmapp (tmabs t e1) e2) e
| rp_ret e1 e2 e : e = subst_prog var_type (e1..) e2 -> red_prog (bind (ret e1) e2) e.
Inductive tred_type : type -> type -> Prop :=
| ct_beta k t1 t2 t : t = subst_type (t2..) t1 -> tred_type (app (abs k t1) t2) t
| ct_abs k t1 t2 : tred_type t1 t2 -> tred_type (abs k t1) (abs k t2)
| ct_app1 t1 t2 t : tred_type t1 t2 -> tred_type (app t1 t) (app t2 t)
| ct_app2 t1 t2 t : tred_type t1 t2 -> tred_type (app t t1) (app t t2)
| ct_arrow1 t1 t2 t : tred_type t1 t2 -> tred_type (arrow t1 t) (arrow t2 t)
| ct_arrow2 t1 t2 t : tred_type t1 t2 -> tred_type (arrow t t1) (arrow t t2)
| ct_pi t1 t2 k : tred_type t1 t2 -> tred_type (pi k t1) (pi k t2)
| ct_comp t1 t2 : tred_type t1 t2 -> tred_type (comp t1) (comp t2).
Definition conv_type :=
clos_refl_sym_trans _ tred_type.
Inductive conv_prog : prog -> prog -> Prop :=
| cp_refl e : conv_prog e e
| cp_sym e1 e2 : conv_prog e1 e2 -> conv_prog e2 e1
| cp_trans e1 e2 e3 : conv_prog e1 e2 -> conv_prog e2 e3 -> conv_prog e1 e3
| cp_tyapp e t1 t2 : conv_type t1 t2 -> conv_prog (tyapp e t1) (tyapp e t2).
Inductive conv_index : index -> index -> Prop :=
| ci_refl o : conv_index o o
| ci_sym o1 o2 : conv_index o1 o2 -> conv_index o2 o1
| ci_trans o1 o2 o3 : conv_index o1 o2 -> conv_index o2 o3 -> conv_index o1 o3
| ci_refb t1 t2 : conv_type t1 t2 -> conv_index (refb t1) (refb t2)
| ci_ref_type t1 t2 o : conv_type t1 t2 -> conv_index (ref t1 o) (ref t2 o)
| ci_ref_index o1 o2 t : conv_index o1 o2 -> conv_index (ref t o1) (ref t o2)
| ci_univ o1 o2 k : conv_index o1 o2 -> conv_index (univ k o1) (univ k o2).
Inductive conv_exp : exp -> exp -> Prop :=
| ce_refl q : conv_exp q q
| ce_sym q1 q2 : conv_exp q1 q2 -> conv_exp q2 q1
| ce_trans q1 q2 q3 : conv_exp q1 q2 -> conv_exp q2 q3 -> conv_exp q2 q3
| ce_beta k q t q' : q' = subst_exp (t..) var_prog var_exp q -> conv_exp (exapp (exabs k q) t) q'
| ce_exabs k q1 q2 : conv_exp q1 q2 -> conv_exp (exabs k q1) (exabs k q2)
| ce_exapp_type t1 t2 q : conv_type t1 t2 -> conv_exp (exapp q t1) (exapp q t2)
| ce_cexp_type t1 t2 q phi : conv_type t1 t2 -> conv_exp (cexp t1 q phi) (cexp t2 q phi)
| ce_cexp_index t q1 q2 phi : conv_index q1 q2 -> conv_exp (cexp t q1 phi) (cexp t q2 phi)
| ce_cexp_spec t q phi psi : conv_spec phi psi -> conv_exp (cexp t q phi) (cexp t q psi)
with conv_spec : spec -> spec -> Prop :=
| cs_refl phi : conv_spec phi phi
| cs_sym phi psi : conv_spec phi psi -> conv_spec psi phi
| cs_trans phi psi theta : conv_spec phi psi -> conv_spec psi theta -> conv_spec phi theta
| cs_implies1 phi1 phi2 psi : conv_spec phi1 phi2 -> conv_spec (spimplies phi1 psi) (spimplies phi2 psi)
| cs_implies2 phi psi1 psi2 : conv_spec psi1 psi2 -> conv_spec (spimplies phi psi1) (spimplies phi psi2)
| cs_after_prog e1 e2 phi : conv_prog e1 e2 -> conv_spec (after e1 phi) (after e2 phi)
| cs_after_spec e phi psi : conv_spec phi psi -> conv_spec (after e phi) (after e psi)
| cs_tyall k phi psi : conv_spec phi psi -> conv_spec (tyall k phi) (tyall k psi)
| cs_tmall_type t1 t2 phi : conv_type t1 t2 -> conv_spec (tmall t1 phi) (tmall t2 phi)
| cs_tmall_spec t phi psi : conv_spec phi psi -> conv_spec (tmall t phi) (tmall t psi)
| cs_spall_index o1 o2 phi : conv_index o1 o2 -> conv_spec (spall o1 phi) (spall o2 phi)
| cs_spall_spec o phi psi : conv_spec phi psi -> conv_spec (spall o phi) (spall o psi)
| cs_holds_prog q1 q2 e1 e2 : conv_prog e1 e2 -> conv_spec (spholds q1 q2 e1) (spholds q1 q2 e2)
| cs_holds_exp1 q1 q1' q2 e : conv_exp q1 q1' -> conv_spec (spholds q1 q2 e) (spholds q1' q2 e)
| cs_holds_exp2 q1 q2 q2' e : conv_exp q2 q2' -> conv_spec (spholds q1 q2 e) (spholds q1 q2' e).
Lemma is_value_ren e sig1 sig2 :
is_value e -> is_value e⟨sig1;sig2⟩.
Proof.
destruct 1; cbn in *; econstructor; eauto.
Qed.
Lemma red_prog_ren e1 e2 sig1 sig2 :
red_prog e1 e2 -> red_prog e1⟨sig1;sig2⟩ e2⟨sig1;sig2⟩.
Proof.
induction 1; cbn in *.
- econstructor 1. rewrite H. now asimpl.
- econstructor 2.
+ rewrite H. now asimpl.
+ now apply is_value_ren.
- econstructor 3. rewrite H. now asimpl.
Qed.
Lemma tred_type_ren t1 t2 xi :
tred_type t1 t2 -> tred_type t1⟨xi⟩ t2⟨xi⟩.
Proof.
induction 1 in xi |-*; cbn.
- apply ct_beta. rewrite H. now asimpl.
- now apply ct_abs.
- now apply ct_app1.
- now apply ct_app2.
- now apply ct_arrow1.
- now apply ct_arrow2.
- now apply ct_pi.
- now apply ct_comp.
Qed.
Lemma conv_type_ren t1 t2 xi :
conv_type t1 t2 -> conv_type t1⟨xi⟩ t2⟨xi⟩.
Proof.
induction 1 in xi |-*; cbn.
- constructor. now apply tred_type_ren.
- constructor 2.
- constructor 3. apply IHclos_refl_sym_trans.
- econstructor 4; [apply IHclos_refl_sym_trans1 | apply IHclos_refl_sym_trans2].
Qed.
Lemma conv_prog_ren e1 e2 sig1 sig2 :
conv_prog e1 e2 -> conv_prog e1⟨sig1;sig2⟩ e2⟨sig1;sig2⟩.
Proof.
induction 1.
- econstructor 1; eauto.
- econstructor 2; eauto.
- econstructor 3; eauto.
- econstructor 4; eauto. now apply conv_type_ren.
Qed.
Lemma conv_index_ren o1 o2 xi :
conv_index o1 o2 -> conv_index o1⟨xi⟩ o2⟨xi⟩.
Proof.
induction 1 in xi |-*; cbn.
- apply ci_refl.
- now apply ci_sym.
- eapply ci_trans; eauto.
- apply ci_refb. now apply conv_type_ren.
- apply ci_ref_type. now apply conv_type_ren.
- now apply ci_ref_index.
- now apply ci_univ.
Qed.
Lemma conv_spec_ren phi psi sig1 sig2 sig3 :
conv_spec phi psi -> conv_spec phi⟨sig1;sig2;sig3⟩ psi⟨sig1;sig2;sig3⟩
with conv_exp_ren q q' sig1 sig2 sig3 :
conv_exp q q' -> conv_exp q⟨sig1;sig2;sig3⟩ q'⟨sig1;sig2;sig3⟩.
Proof.
induction 1 in sig1, sig2, sig3 |- *; cbn in *.
- econstructor 1; eauto.
- econstructor 2; eauto.
- econstructor 3; eauto.
- econstructor 4; eauto.
- econstructor 5; eauto.
- econstructor 6; eauto. now apply conv_prog_ren.
- econstructor 7; eauto.
- econstructor 8; eauto.
- econstructor 9; eauto. now apply conv_type_ren.
- econstructor 10; eauto.
- econstructor 11; eauto. now apply conv_index_ren.
- econstructor 12; eauto.
- econstructor 13; eauto. now apply conv_prog_ren.
- fold ren_exp. econstructor 14; eauto.
- fold ren_exp. econstructor 15; eauto.
- induction 1 in sig1, sig2, sig3 |- *; cbn in *.
+ econstructor 1; eauto.
+ econstructor 2; eauto.
+ econstructor 3; eauto.
+ econstructor 4; eauto. rewrite H. now asimpl.
+ econstructor 5; eauto.
+ econstructor 6; eauto. now apply conv_type_ren.
+ fold ren_exp. econstructor 7; eauto. now apply conv_type_ren.
+ fold ren_spec. econstructor 8; eauto. now apply conv_index_ren.
+ fold ren_spec. econstructor 9; eauto.
Qed.
Lemma tred_type_subst t1 t2 xi :
tred_type t1 t2 -> tred_type t1[xi] t2[xi].
Proof.
induction 1 in xi |-*; cbn.
- apply ct_beta. rewrite H. now asimpl.
- now apply ct_abs.
- now apply ct_app1.
- now apply ct_app2.
- now apply ct_arrow1.
- now apply ct_arrow2.
- now apply ct_pi.
- now apply ct_comp.
Qed.
Lemma conv_type_subst t1 t2 xi :
conv_type t1 t2 -> conv_type t1[xi] t2[xi].
Proof.
induction 1 in xi |-*; cbn.
- constructor. now apply tred_type_subst.
- constructor 2.
- constructor 3. apply IHclos_refl_sym_trans.
- econstructor 4; [apply IHclos_refl_sym_trans1 | apply IHclos_refl_sym_trans2].
Qed.
Notation lup := nth_error.
Lemma lup_map_el X Y (f : X -> Y) L n y :
lup (map f L) n = Some y -> exists x, lup L n = Some x /\ y = f x.
Proof.
revert L. induction n; destruct L; cbn.
- discriminate.
- intros [=]; subst. now exists x.
- discriminate.
- apply IHn.
Qed.
Definition kind := nat.
Inductive has_kind (Delta : list kind) : type -> kind -> Prop :=
| hk_var X k : lup Delta X = Some k
-> has_kind Delta (var_type X) k
| hk_app t1 t2 k : has_kind Delta t1 (S k)
-> has_kind Delta t2 k
-> has_kind Delta (app t1 t2) 0
| hk_abs t k : has_kind (k :: Delta) t 0
-> has_kind Delta (abs k t) (S k)
| hk_arrow t1 t2 : has_kind Delta t1 0
-> has_kind Delta t2 0
-> has_kind Delta (arrow t1 t2) 0
| hk_pi t k : has_kind (k::Delta) t 0
-> has_kind Delta (pi k t) 0
| hk_comp t : has_kind Delta t 0
-> has_kind Delta (comp t) 0.
Inductive has_type (Delta : list kind) (Gamma : list type) : prog -> type -> Prop :=
| ht_var x t : lup Gamma x = Some t
-> has_type Delta Gamma (var_prog x) t
| ht_tyabs e t k : has_type (k :: Delta) (map (ren_type ↑) Gamma) e t
-> has_type Delta Gamma (tyabs k e) (pi k t)
| ht_tmabs e t1 t2 : has_type Delta (t1 :: Gamma) e t2
-> has_type Delta Gamma (tmabs t1 e) (arrow t1 t2)
| ht_ret e t : has_type Delta Gamma e t
-> has_type Delta Gamma (ret e) (comp t)
| ht_bind e1 e2 t1 t2 : has_type Delta Gamma e1 (comp t1)
-> has_type Delta (t1 :: Gamma) e2 (comp t2)
-> has_type Delta Gamma (bind e1 e2) (comp t2)
| ht_tyapp e t1 t2 k : has_type Delta Gamma e (pi k t1)
-> has_kind Delta t2 k
-> has_type Delta Gamma (tyapp e t2) t1[t2..]
| ht_tmapp e1 e2 t1 t2 : has_type Delta Gamma e1 (arrow t1 t2)
-> has_type Delta Gamma e2 t1
-> has_type Delta Gamma (tmapp e1 e2) t2
| ht_conv e t1 t2 : conv_type t1 t2
-> has_type Delta Gamma e t1
-> has_type Delta Gamma e t2.
Inductive is_index (Delta : list kind) : index -> Prop :=
| ii_refb t : has_kind Delta t 0 -> is_index Delta (refb t)
| ii_ref o t : has_kind Delta t 0 -> is_index Delta o -> is_index Delta (ref t o)
| ii_univ o k : is_index (k :: Delta) o -> is_index Delta (univ k o).
Inductive has_index (Delta : list kind) (Gamma : list type) (Sigma : list index) : exp -> index -> Prop :=
| hi_var q o : lup Sigma q = Some o
-> has_index Delta Gamma Sigma (var_exp q) o
| hi_cexp phi t o : is_spec Delta (t :: Gamma) (o :: Sigma) phi
-> has_index Delta Gamma Sigma (cexp t o phi) (ref t o)
| hi_exabs q k o : has_index (k :: Delta) (map (ren_type ↑) Gamma) (map (ren_index ↑) Sigma) q o
-> has_index Delta Gamma Sigma (exabs k q) (univ k o)
| hi_exapp q k t o : has_index Delta Gamma Sigma q (univ k o)
-> has_kind Delta t k
-> has_index Delta Gamma Sigma (exapp q t) o[t..]
| hi_conv e o1 o2 : conv_index o1 o2
-> has_index Delta Gamma Sigma e o1
-> has_index Delta Gamma Sigma e o2
with is_spec (Delta : list kind) (Gamma : list type) (Sigma : list index) : spec -> Prop :=
| is_implies phi psi : is_spec Delta Gamma Sigma phi
-> is_spec Delta Gamma Sigma psi
-> is_spec Delta Gamma Sigma (spimplies phi psi)
| is_after phi e t : is_spec Delta (t :: Gamma) Sigma phi
-> has_type Delta Gamma e (comp t)
-> is_spec Delta Gamma Sigma (after e phi)
| is_tyall phi k : is_spec (k :: Delta) (map (ren_type ↑) Gamma) (map (ren_index ↑) Sigma) phi
-> is_spec Delta Gamma Sigma (tyall k phi)
| is_tmall phi t : is_spec Delta (t :: Gamma) Sigma phi
-> is_spec Delta Gamma Sigma (tmall t phi)
| is_spall phi o : is_spec Delta Gamma (o :: Sigma) phi
-> is_index Delta o
-> is_spec Delta Gamma Sigma (spall o phi)
| is_holds e t q q' o : has_type Delta Gamma e t
-> has_index Delta Gamma Sigma q (ref t o)
-> has_index Delta Gamma Sigma q' o
-> is_spec Delta Gamma Sigma (spholds q q' e).
Lemma lup_app X (A B : list X) n x :
lup A n = Some x -> lup (A ++ B) n = Some x.
Proof.
intros H. rewrite nth_error_app1; trivial. apply nth_error_Some. congruence.
Qed.
Lemma has_kind_weak Delta Delta' t k :
has_kind Delta t k -> has_kind (Delta ++ Delta') t k.
Proof.
induction 1; cbn; try now (econstructor; eauto).
constructor. now apply lup_app.
Qed.
Lemma has_type_weak Delta Delta' Gamma Gamma' e t :
has_type Delta Gamma e t -> has_type (Delta ++ Delta') (Gamma ++ Gamma') e t.
Proof.
induction 1 in Delta', Gamma' |- *; cbn; try now (econstructor; eauto).
- constructor. now apply lup_app.
- constructor. rewrite map_app. eauto.
- econstructor; eauto. now apply has_kind_weak.
Qed.
Lemma has_kind_ren Delta Delta' t k xi :
has_kind Delta t k
-> (forall x k', lup Delta x = Some k' -> lup Delta' (xi x) = Some k')
-> has_kind Delta' t⟨xi⟩ k.
Proof.
induction 1 in Delta', xi |- *; cbn; intros HD.
- apply hk_var. now apply HD.
- apply hk_app with k; intuition.
- apply hk_abs. apply IHhas_kind. intros []; firstorder.
- apply hk_arrow; intuition.
- apply hk_pi. apply IHhas_kind. intros []; firstorder.
- apply hk_comp. now apply IHhas_kind.
Qed.
Lemma has_type_ren Delta Delta' Gamma Gamma' xi rho e t :
has_type Delta Gamma e t
-> (forall n k, lup Delta n = Some k -> lup Delta' (xi n) = Some k)
-> (forall n t', lup Gamma n = Some t' -> lup Gamma' (rho n) = Some (ren_type xi t'))
-> has_type Delta' Gamma' (ren_prog xi rho e) (ren_type xi t).
Proof.
induction 1 in xi, rho, Delta', Gamma' |- *; intros HD HG; cbn.
- apply ht_var. now apply HG.
- apply ht_tyabs. apply IHhas_type.
+ intros []; cbn; intuition.
+ intros n0 t' H0. rewrite nth_error_map in H0.
destruct (lup Gamma n0) eqn: He; cbn in *; try discriminate.
injection H0 as []. erewrite renRen_type, extRen_type, <- renRen_type.
* apply map_nth_error. now apply HG.
* now intros [].
- apply ht_tmabs. apply IHhas_type.
+ intros []; cbn; intuition.
+ intros []; cbn; intros; try now injection H0 as ->. now apply HG.
- apply ht_ret. apply IHhas_type; eauto.
- apply ht_bind with t1⟨xi⟩.
+ apply IHhas_type1; eauto.
+ apply IHhas_type2; eauto. intros []; cbn; intuition.
unfold upRen_prog_type. now injection H1 as ->.
- cbn. asimpl. erewrite ext_type, <- renSubst_type at 1.
+ apply ht_tyapp with k.
* apply IHhas_type; eauto.
* eapply has_kind_ren; try apply H0. apply HD.
+ now intros [].
- apply ht_tmapp with t1⟨xi⟩.
+ apply IHhas_type1; eauto.
+ apply IHhas_type2; eauto.
- apply ht_conv with t1⟨xi⟩.
+ now apply conv_type_ren.
+ apply IHhas_type; eauto.
Qed.
Lemma is_index_ren Delta Delta' xi o :
is_index Delta o
-> (forall n k, lup Delta n = Some k -> lup Delta' (xi n) = Some k)
-> is_index Delta' o⟨xi⟩.
Proof.
induction 1 in Delta', xi |- *; intros HD; cbn.
- apply ii_refb. now apply (has_kind_ren H).
- apply ii_ref; try now apply (has_kind_ren H). now apply IHis_index; try apply H3.
- apply ii_univ. apply IHis_index; try apply H1. intros []; cbn in *; intuition.
Qed.
Lemma is_spec_ren Delta Delta' Gamma Gamma' Sigma Sigma' tren pren eren phi :
is_spec Delta Gamma Sigma phi
-> (forall n k, lup Delta n = Some k -> lup Delta' (tren n) = Some k)
-> (forall n t, lup Gamma n = Some t -> lup Gamma' (pren n) = Some (ren_type tren t))
-> (forall n o, lup Sigma n = Some o -> lup Sigma' (eren n) = Some (ren_index tren o))
-> is_spec Delta' Gamma' Sigma' (ren_spec tren pren eren phi)
with has_index_ren Delta Delta' Gamma Gamma' Sigma Sigma' tren pren eren q o :
has_index Delta Gamma Sigma q o
-> (forall n k, lup Delta n = Some k -> lup Delta' (tren n) = Some k)
-> (forall n t, lup Gamma n = Some t -> lup Gamma' (pren n) = Some (ren_type tren t))
-> (forall n o, lup Sigma n = Some o -> lup Sigma' (eren n) = Some (ren_index tren o))
-> has_index Delta' Gamma' Sigma' (ren_exp tren pren eren q) o⟨tren⟩.
Proof.
induction 1 in Delta', Gamma', Sigma', tren, pren, eren |- *; intros HD HG HS; cbn.
- apply is_implies; eauto.
- apply is_after with t⟨tren⟩.
+ apply IHis_spec; eauto. destruct n; cbn in *; intuition. now injection H1 as ->.
+ eapply has_type_ren in H0; eauto.
- apply is_tyall. apply IHis_spec; eauto.
+ intros [] k'; cbn; intuition.
+ intros n0 t' H0. rewrite nth_error_map in H0.
destruct (lup Gamma n0) eqn: He; cbn in *; try discriminate.
injection H0 as []. erewrite renRen_type, extRen_type, <- renRen_type.
* apply map_nth_error. now apply HG.
* now intros [].
+ intros n0 t' H0. rewrite nth_error_map in H0.
destruct (lup Sigma n0) eqn: He; cbn in *; try discriminate.
injection H0 as []. erewrite renRen_index, extRen_index, <- renRen_index.
* apply map_nth_error. now apply HS.
* now intros [].
- apply is_tmall. apply IHis_spec; eauto.
intros [] t0; cbn; try apply HG.
intros [=]; subst. reflexivity.
- apply is_spall; try eapply is_index_ren; eauto. apply IHis_spec; try apply H2; intuition.
destruct n; cbn in *; intuition. now injection H1 as ->.
- eapply is_holds.
+ eapply has_type_ren; try apply H; intuition.
+ eapply has_index_ren in H0; eauto.
+ fold ren_index. eapply has_index_ren in H1; eauto.
- induction 1 in Delta', Gamma', Sigma', tren, pren, eren |- *; intros HD HG HS; cbn.
+ apply hi_var. now apply HS.
+ apply hi_cexp. eapply is_spec_ren; try apply H; intuition.
* destruct n; cbn in *; intuition. now injection H0 as ->.
* destruct n; cbn in *; intuition. now injection H0 as ->.
+ apply hi_exabs. apply IHhas_index; intuition.
* destruct n; cbn in *; intuition.
* rewrite nth_error_map in H0.
destruct (lup Gamma n) eqn: He; cbn in *; try discriminate.
injection H0 as []. erewrite renRen_type, extRen_type, <- renRen_type.
-- apply map_nth_error. now apply HG.
-- now intros [].
* rewrite nth_error_map in H0.
destruct (lup Sigma n) eqn: He; cbn in *; try discriminate.
injection H0 as []. erewrite renRen_index, extRen_index, <- renRen_index.
-- apply map_nth_error. now apply HS.
-- now intros [].
+ erewrite compSubstRen_index, ext_index, <- compRenSubst_index. eapply hi_exapp.
apply IHhas_index; try apply H; intuition. 2,3: reflexivity.
* eapply has_kind_ren; eauto.
* now intros [].
+ apply hi_conv with o1⟨tren⟩.
* now apply conv_index_ren.
* apply IHhas_index; eauto.
Qed.
Lemma is_spec_ren' Delta Gamma Gamma' Sigma xi phi :
is_spec Delta Gamma Sigma phi
-> (forall n t, lup Gamma n = Some t -> lup Gamma' (xi n) = Some t)
-> is_spec Delta Gamma' Sigma (ren_spec id xi id phi).
Proof.
intros H1 H2. eapply is_spec_ren; try apply H1; intuition.
- rewrite rinstId'_type. intuition.
- rewrite rinstId'_index. intuition.
Qed.
Lemma has_kind_subst Delta Delta' t k sigma :
has_kind Delta t k
-> (forall x k', lup Delta x = Some k' -> has_kind Delta' (sigma x) k')
-> has_kind Delta' t[sigma] k.
Proof.
induction 1 in Delta', sigma |- *; cbn; intros HD.
- now apply HD.
- apply hk_app with k; intuition.
- apply hk_abs. apply IHhas_kind. intros []; cbn.
+ intros k' [=]; subst. now constructor.
+ intros k' Hk. apply HD in Hk. eapply has_kind_ren; eauto.
- apply hk_arrow; intuition.
- apply hk_pi. apply IHhas_kind. intros []; cbn.
+ intros k' [=]; subst. now constructor.
+ intros k' Hk. apply HD in Hk. eapply has_kind_ren; eauto.
- apply hk_comp. now apply IHhas_kind.
Qed.
Lemma has_type_subst Delta Delta' Gamma Gamma' e t sig1 sig2 :
has_type Delta Gamma e t
-> (forall n k, lup Delta n = Some k -> has_kind Delta' (sig1 n) k)
-> (forall n t, lup Gamma n = Some t -> has_type Delta' Gamma' (sig2 n) t[sig1])
-> has_type Delta' Gamma' (subst_prog sig1 sig2 e) t[sig1].
Proof.
induction 1 in Delta', Gamma', sig1, sig2 |-*; cbn in *; intros H1 H2.
- now apply H2.
- constructor 2. apply IHhas_type.
+ intros [] k'; cbn.
* intros [=]; subst. now constructor.
* intros H'. apply H1 in H'. eapply has_kind_ren; eauto.
+ intros n t' H'. apply lup_map_el in H' as [t0[Ht ->]].
apply H2 in Ht. asimpl. rewrite <- substRen_type.
eapply has_type_ren; try apply Ht; trivial.
intros. now apply map_nth_error.
- constructor 3. erewrite ext_prog. apply (IHhas_type _ _ sig1 (up_prog_prog sig2)); trivial.
+ intros [] t; cbn.
* intros [=]; subst. now constructor.
* intros H'. apply H2 in H'. setoid_rewrite <- rinstId'_type at 3.
eapply has_type_ren; try apply H'; cbn; trivial.
setoid_rewrite rinstId'_type. trivial.
+ unfold up_prog_type. intros n. apply rinstId'_type.
+ reflexivity.
- constructor 4. apply IHhas_type; trivial.
- econstructor 5.
+ eapply IHhas_type1; trivial.
+ erewrite ext_prog. apply (IHhas_type2 _ _ sig1 (up_prog_prog sig2)); trivial.
* intros [] t; cbn.
-- intros [=]; subst. now constructor.
-- intros H'. apply H2 in H'. setoid_rewrite <- rinstId'_type at 3.
eapply has_type_ren; try apply H'; cbn; trivial.
setoid_rewrite rinstId'_type. trivial.
* unfold up_prog_type. intros n. apply rinstId'_type.
* reflexivity.
- replace (t1[t2..][sig1]) with (t1[up_type_type sig1][t2[sig1]..]) by now asimpl.
econstructor 6. apply IHhas_type; trivial.
eapply has_kind_subst; try apply H0. assumption.
- econstructor 7.
+ eapply IHhas_type1; trivial.
+ eapply IHhas_type2; trivial.
- econstructor 8.
+ apply conv_type_subst, H.
+ now apply IHhas_type.
Qed.
Lemma has_type_subst' Delta Gamma Gamma' e t sigma :
has_type Delta Gamma e t
-> (forall n t, lup Gamma n = Some t -> has_type Delta Gamma' (sigma n) t)
-> has_type Delta Gamma' (subst_prog var_type sigma e) t.
Proof.
intros. setoid_rewrite <- instId'_type. eapply has_type_subst; try apply H.
- intros. now constructor.
- setoid_rewrite instId'_type. assumption.
Qed.
Inductive treds_type : type -> type -> Prop :=
| ct_tred t t' : tred_type t t' -> treds_type t t'
| ct_refl t : treds_type t t
| ct_trans t t' t'' : tred_type t t' -> treds_type t' t'' -> treds_type t t''.
Lemma treds_type_trans t1 t2 t3 :
treds_type t1 t2 -> treds_type t2 t3 -> treds_type t1 t3.
Proof.
induction 1 in t3 |- *.
- now apply ct_trans.
- tauto.
- intros H' % IHtreds_type. eapply ct_trans; eauto.
Qed.
Inductive ptred : type -> type -> Prop :=
| pt_var x : ptred (var_type x) (var_type x)
| pt_beta k t1 t2 t1' t2' t : t = subst_type (t2'..) t1' -> ptred t1 t1' -> ptred t2 t2' -> ptred (app (abs k t1) t2) t
| pt_abs k t1 t2 : ptred t1 t2 -> ptred (abs k t1) (abs k t2)
| pt_app t1 t2 t1' t2' : ptred t1 t1' -> ptred t2 t2' -> ptred (app t1 t2) (app t1' t2')
| pt_arrow t1 t2 t1' t2' : ptred t1 t1' -> ptred t2 t2' -> ptred (arrow t1 t2) (arrow t1' t2')
| pt_pi t1 t2 k : ptred t1 t2 -> ptred (pi k t1) (pi k t2)
| pt_comp t1 t2 : ptred t1 t2 -> ptred (comp t1) (comp t2).
Inductive ptreds : type -> type -> Prop :=
| pt_ptred t t' : ptred t t' -> ptreds t t'
| pt_trans t t' t'' : ptred t t' -> ptreds t' t'' -> ptreds t t''.
Lemma treds_app1 t1 t2 t :
treds_type t1 t2 -> treds_type (app t1 t) (app t2 t).
Proof.
induction 1.
- constructor. now apply ct_app1.
- constructor 2.
- econstructor 3; eauto. now apply ct_app1.
Qed.
Lemma treds_app2 t1 t2 t :
treds_type t1 t2 -> treds_type (app t t1) (app t t2).
Proof.
induction 1.
- constructor. now apply ct_app2.
- constructor 2.
- econstructor 3; eauto. now apply ct_app2.
Qed.
Lemma treds_arrow1 t1 t2 t :
treds_type t1 t2 -> treds_type (arrow t1 t) (arrow t2 t).
Proof.
induction 1.
- constructor. now apply ct_arrow1.
- constructor 2.
- econstructor 3; eauto. now apply ct_arrow1.
Qed.
Lemma treds_arrow2 t1 t2 t :
treds_type t1 t2 -> treds_type (arrow t t1) (arrow t t2).
Proof.
induction 1.
- constructor. now apply ct_arrow2.
- constructor 2.
- econstructor 3; eauto. now apply ct_arrow2.
Qed.
Lemma treds_abs t1 t2 k :
treds_type t1 t2 -> treds_type (abs k t1) (abs k t2).
Proof.
induction 1.
- constructor. now apply ct_abs.
- constructor 2.
- econstructor 3; eauto. now apply ct_abs.
Qed.
Lemma treds_pi t1 t2 k :
treds_type t1 t2 -> treds_type (pi k t1) (pi k t2).
Proof.
induction 1.
- constructor. now apply ct_pi.
- constructor 2.
- econstructor 3; eauto. now apply ct_pi.
Qed.
Lemma treds_comp t1 t2 :
treds_type t1 t2 -> treds_type (comp t1) (comp t2).
Proof.
induction 1.
- constructor. now apply ct_comp.
- constructor 2.
- econstructor 3; eauto. now apply ct_comp.
Qed.
Lemma ptred_treds t t' :
ptred t t' -> treds_type t t'.
Proof.
induction 1.
- constructor 2.
- eapply treds_type_trans. 2: constructor; apply ct_beta; eauto.
eapply treds_type_trans.
+ apply treds_app1, treds_abs, IHptred1.
+ apply treds_app2, IHptred2.
- now apply treds_abs.
- eapply treds_type_trans.
+ apply treds_app1. eauto.
+ eapply treds_app2. eauto.
- eapply treds_type_trans.
+ apply treds_arrow1. eauto.
+ eapply treds_arrow2. eauto.
- now apply treds_pi.
- now apply treds_comp.
Qed.
Lemma ptreds_treds t t' :
ptreds t t' -> treds_type t t'.
Proof.
induction 1.
- now apply ptred_treds.
- eapply treds_type_trans; eauto. now apply ptred_treds.
Qed.
Lemma ptred_refl t :
ptred t t.
Proof.
induction t; now constructor.
Qed.
Lemma tred_ptred t t' :
tred_type t t' -> ptred t t'.
Proof.
induction 1; econstructor; eauto; apply ptred_refl.
Qed.
Lemma treds_ptreds t t' :
treds_type t t' -> ptreds t t'.
Proof.
induction 1.
- constructor 1. now apply tred_ptred.
- constructor 1. apply ptred_refl.
- econstructor 2; eauto. now apply tred_ptred.
Qed.
Fixpoint maxred t :=
match t with
| var_type x => var_type x
| app (abs k t) t' => subst_type ((maxred t')..) (maxred t)
| app t t' => app (maxred t) (maxred t')
| abs k t => abs k (maxred t)
| arrow t t' => arrow (maxred t) (maxred t')
| pi k t => pi k (maxred t)
| comp t => comp (maxred t)
end.
Lemma ptred_ren t1 t1' xi :
ptred t1 t1' -> ptred t1⟨xi⟩ t1'⟨xi⟩.
Proof.
induction 1 in xi |- *; cbn; try now (constructor; eauto).
subst. econstructor; eauto. now asimpl.
Qed.
Lemma ptred_subst t1 t1' sig sig' :
ptred t1 t1' -> (forall n, ptred (sig n) (sig' n)) -> ptred t1[sig] t1'[sig'].
Proof.
induction 1 in sig, sig' |- *; cbn; intros H'; try now (constructor; eauto).
- apply H'.
- subst. econstructor; eauto. 2: apply (IHptred1 _ (up_type_type sig')).
+ now asimpl.
+ intros []; cbn; try constructor. apply ptred_ren, H'.
- constructor. apply IHptred. intros []; cbn; try constructor. apply ptred_ren, H'.
- constructor. apply IHptred. intros []; cbn; try constructor. apply ptred_ren, H'.
Qed.
Lemma ptred_subst' t1 t1' t2 t2' :
ptred t1 t1' -> ptred t2 t2' -> ptred t1[t2..] t1'[t2'..].
Proof.
intros H1 H2. apply ptred_subst; trivial.
intros []; cbn; trivial. constructor.
Qed.
Lemma maxred_ptred t t' :
ptred t t' -> ptred t' (maxred t).
Proof.
induction t in t' |- *; inversion 1; subst; cbn.
- constructor.
- apply ptred_subst'; eauto.
specialize (IHt1 (abs k t1') (pt_abs _ H3)).
cbn in IHt1. inversion IHt1; subst. apply H1.
- destruct t1; cbn.
+ inversion H2; subst. constructor; eauto.
+ inversion H2; subst; constructor; eauto.
+ inversion H2; subst. eapply pt_beta; eauto.
specialize (IHt1 (abs n t3) (pt_abs _ H5)).
cbn in IHt1. inversion IHt1; subst. apply H1.
+ inversion H2; subst. constructor; eauto.
+ inversion H2; subst. constructor; eauto.
+ inversion H2; subst. constructor; eauto.
- constructor. eauto.
- constructor; eauto.
- constructor. eauto.
- constructor. eauto.
Qed.
Lemma Diamond_ptred t t1 t2 :
ptred t t1 -> ptred t t2 -> { t' | ptred t1 t' /\ ptred t2 t' }.
Proof.
intros H1 H2. exists (maxred t). split; now apply maxred_ptred.
Qed.
Lemma Church_Rosser_ptreds' t t1 t2 :
ptred t t1 -> ptreds t t2 -> exists t', ptreds t1 t' /\ ptred t2 t'.
Proof.
intros H. induction 1 in t1, H |- *.
- destruct (Diamond_ptred H H0) as (t0 & H1 & H2).
exists t0. split; trivial. now constructor.
- destruct (Diamond_ptred H H0) as (t0 & H2 & H3).
destruct (IHptreds t0 H3) as (t2 & H4 & H5).
exists t2. split; trivial. econstructor 2; eauto.
Qed.
Lemma Church_Rosser_ptreds t t1 t2 :
ptreds t t1 -> ptreds t t2 -> exists t', ptreds t1 t' /\ ptreds t2 t'.
Proof.
induction 1 in t2 |-*; intros H1.
- destruct (Church_Rosser_ptreds' H H1) as (t1 & H2 & H3).
exists t1. split; trivial. now constructor.
- destruct (Church_Rosser_ptreds' H H1) as (t1 & H2 & H3).
destruct (IHptreds t1 H2) as (t3 & H4 & H5).
exists t3. split; trivial. econstructor 2; eauto.
Qed.
Lemma Church_Rosser t t1 t2 :
treds_type t t1 -> treds_type t t2 -> exists t', treds_type t1 t' /\ treds_type t2 t'.
Proof.
intros H1 % treds_ptreds H2 % treds_ptreds.
destruct (Church_Rosser_ptreds H1 H2) as [t' H].
exists t'. split; apply ptreds_treds, H.
Qed.
Lemma Church_Rosser' t1 t2 :
conv_type t1 t2 -> exists t, treds_type t1 t /\ treds_type t2 t.
Proof.
induction 1.
- exists y. split; now constructor.
- exists x. split; now constructor.
- firstorder eauto.
- destruct IHclos_refl_sym_trans1 as [t1 H1], IHclos_refl_sym_trans2 as [t2 H2].
destruct (@Church_Rosser y t1 t2) as [t Ht]; intuition.
exists t. split; eapply treds_type_trans; eauto.
Qed.
Lemma treds_conv t t' :
treds_type t t' -> conv_type t t'.
Proof.
induction 1.
- now constructor 1.
- constructor 2.
- econstructor 4; eauto. now constructor 1.
Qed.
Lemma treds_comp_inv' t1 t2' :
treds_type (comp t1) t2' -> exists t2, t2' = comp t2.
Proof.
remember (comp t1) as t1'.
induction 1 in t1, Heqt1' |- *; subst.
- inversion H; subst. now exists t2.
- now exists t1.
- inversion H; subst. eapply IHtreds_type. reflexivity.
Qed.
Lemma treds_comp_inv t1 t2 :
treds_type (comp t1) (comp t2) -> treds_type t1 t2.
Proof.
remember (comp t1) as t. remember (comp t2) as t'.
induction 1 in t1, t2, Heqt, Heqt' |- *; subst.
- constructor 1. inversion H; subst. apply H2.
- injection Heqt'. intros ->. constructor 2.
- inversion H; subst. eapply ct_trans; eauto.
Qed.
Lemma conv_comp_inv t1 t2 :
conv_type (comp t1) (comp t2) -> conv_type t1 t2.
Proof.
intros (t & H1 & H2) % Church_Rosser'.
destruct (treds_comp_inv' H1) as [t1' ->].
apply treds_comp_inv in H1, H2. econstructor 4.
- apply treds_conv. apply H1.
- constructor 3. now apply treds_conv.
Qed.
Lemma ht_ret_inv' Delta Gamma e t e' t' :
has_type Delta Gamma e' t' -> e' = ret e -> conv_type t' (comp t) -> has_type Delta Gamma e t.
Proof.
induction 1 in e, t |- *; try discriminate.
- intros [=] H' % conv_comp_inv; subst. eapply ht_conv; eauto.
- intros H1 H2. apply IHhas_type; trivial. econstructor 4; eauto.
Qed.
Lemma ht_ret_inv Delta Gamma e t :
has_type Delta Gamma (ret e) (comp t) -> has_type Delta Gamma e t.
Proof.
intros H. eapply ht_ret_inv'; eauto. constructor 2.
Qed.
Lemma treds_pi_inv' t1 t2' k :
treds_type (pi k t1) t2' -> exists t2, t2' = pi k t2.
Proof.
remember (pi k t1) as t1'.
induction 1 in t1, Heqt1' |- *; subst.
- inversion H; subst. now exists t2.
- now exists t1.
- inversion H; subst. eapply IHtreds_type. reflexivity.
Qed.
Lemma treds_pi_inv t1 t2 k k' :
treds_type (pi k t1) (pi k' t2) -> treds_type t1 t2 /\ k = k'.
Proof.
remember (pi k t1) as t. remember (pi k' t2) as t'.
induction 1 in t1, t2, Heqt, Heqt' |- *; subst.
- inversion H; subst. split; trivial. constructor 1. apply H1.
- injection Heqt'. intros -> ->. split; trivial. constructor 2.
- inversion H; subst. split.
+ eapply ct_trans; eauto. now apply IHtreds_type.
+ now apply (IHtreds_type t3 t2).
Qed.
Lemma conv_pi_inv k k' t t' :
conv_type (pi k t) (pi k' t') -> conv_type t t' /\ k = k'.
Proof.
intros (t'' & H1 & H2) % Church_Rosser'.
destruct (treds_pi_inv' H1) as [t1' ->].
apply treds_pi_inv in H1, H2 as [H2 ->]. split; trivial. econstructor 4.
- apply treds_conv. apply H1.
- constructor 3. now apply treds_conv.
Qed.
Lemma ht_tyabs_inv' Delta Gamma e t k k' e' t' :
has_type Delta Gamma e' t' -> e' = tyabs k e -> conv_type t' (pi k' t)
-> has_type (k :: Delta) (list_map (ren_type ↑) Gamma) e t /\ k = k'.
Proof.
induction 1 in e, t |- *; try discriminate.
- intros [=] H'; subst. apply conv_pi_inv in H' as [H' ->]. split; trivial. eapply ht_conv; eauto.
- intros H1 H2. apply IHhas_type; trivial. econstructor 4; eauto.
Qed.
Lemma ht_tyabs_inv Delta Gamma e t k k' :
has_type Delta Gamma (tyabs k e) (pi k' t)
-> has_type (k :: Delta) (list_map (ren_type ↑) Gamma) e t /\ k = k'.
Proof.
intros H. eapply ht_tyabs_inv'; eauto. constructor 2.
Qed.
Lemma treds_arrow_inv' t1 t2 t' :
treds_type (arrow t1 t2) t' -> exists t1' t2', t' = arrow t1' t2'.
Proof.
remember (arrow t1 t2) as t.
induction 1 in t1, t2, Heqt |- *; subst.
- inversion H; subst.
+ now exists t3, t2.
+ now exists t1, t3.
- now exists t1, t2.
- inversion H; subst.
+ eapply IHtreds_type. reflexivity.
+ eapply IHtreds_type. reflexivity.
Qed.
Lemma treds_arrow_inv t1 t2 t1' t2' :
treds_type (arrow t1 t2) (arrow t1' t2') -> treds_type t1 t1' /\ treds_type t2 t2'.
Proof.
remember (arrow t1 t2) as t. remember (arrow t1' t2') as t'.
induction 1 in t1, t2, Heqt, Heqt' |- *; subst.
- inversion H; subst.
+ split; try constructor 2. now constructor 1.
+ split; try constructor 2. now constructor 1.
- injection Heqt'. intros -> ->. split; constructor 2.
- inversion H; subst; split.
+ eapply ct_trans; eauto. now apply (IHtreds_type t3 t2).
+ now apply (IHtreds_type t3 t2).
+ now apply (IHtreds_type t1 t3).
+ eapply ct_trans; eauto. now apply (IHtreds_type t1 t3).
Qed.
Lemma conv_arrow_inv t1 t2 t1' t2' :
conv_type (arrow t1 t2) (arrow t1' t2') -> conv_type t1 t1' /\ conv_type t2 t2'.
Proof.
intros (t'' & H1 & H2) % Church_Rosser'.
destruct (treds_arrow_inv' H1) as [t [t' ->]].
apply treds_arrow_inv in H1 as [H1 H1'], H2 as [H2 H2']. split; econstructor 4.
- apply treds_conv. apply H1.
- constructor 3. now apply treds_conv.
- apply treds_conv. apply H1'.
- constructor 3. now apply treds_conv.
Qed.
Lemma ht_tmabs_inv' Delta Gamma e t t1 t2 e' t' :
has_type Delta Gamma e' t' -> e' = tmabs t e -> conv_type t' (arrow t1 t2)
-> has_type Delta (t :: Gamma) e t2 /\ conv_type t t1.
Proof.
induction 1 in e, t |- *; try discriminate.
- intros [=] H'; subst. apply conv_arrow_inv in H' as [H1 H2].
split; trivial. eapply ht_conv; eauto.
- intros H1 H2. apply IHhas_type; trivial. econstructor 4; eauto.
Qed.
Lemma ht_tmabs_inv Delta Gamma e t t1 t2 :
has_type Delta Gamma (tmabs t e) (arrow t1 t2)
-> has_type Delta (t :: Gamma) e t2 /\ conv_type t t1.
Proof.
intros H. eapply ht_tmabs_inv'; eauto. constructor 2.
Qed.
Lemma red_has_type Delta Gamma e e' t :
has_type Delta Gamma e t -> red_prog e e' -> has_type Delta Gamma e' t.
Proof.
induction 1 in e' |- *. 1-7: inversion 1; subst.
- eapply has_type_subst'; eauto. intros []; cbn.
+ intros t [=]; subst. now apply ht_ret_inv in H.
+ intros t. apply ht_var.
- apply ht_tyabs_inv in H as [H <-]. eapply has_type_subst; eauto.
+ intros []; cbn. intros k' [=]; subst; trivial. intros k'. apply hk_var.
+ intros n t (t' & Ht & ->) % lup_map_el. asimpl. now constructor.
- apply ht_tmabs_inv in H as [H H']. eapply has_type_subst'; eauto.
intros []; cbn. intros t' [=]; subst.
+ eapply ht_conv; eauto. now constructor 3.
+ intros k'. apply ht_var.
- intros H' % IHhas_type. eapply ht_conv; eauto.
Qed.
Definition swap := 0 .: (↑ >> ↑).
Inductive HOPL_prv (A : list spec) : spec -> Prop :=
| HOPL_CTX phi : In phi A
-> HOPL_prv A phi
| HOPL_II phi psi : HOPL_prv (phi :: A) psi
-> HOPL_prv A (spimplies phi psi)
| HOPL_IE phi psi : HOPL_prv A (spimplies phi psi)
-> HOPL_prv A phi
-> HOPL_prv A psi
| HOPL_TAI phi k : HOPL_prv (map (ren_spec ↑ id id) A) phi
-> HOPL_prv A (tyall k phi)
| HOPL_TAE phi k t : HOPL_prv A (tyall k phi)
-> HOPL_prv A (subst_spec (t..) var_prog var_exp phi)
| HOPL_EAI phi t : HOPL_prv (map (ren_spec id ↑ id) A) phi
-> HOPL_prv A (tmall t phi)
| HOPL_EAE phi e t : HOPL_prv A (tmall t phi)
-> HOPL_prv A (subst_spec var_type (e..) var_exp phi)
| HOPL_SAI phi o : HOPL_prv (map (ren_spec id id ↑) A) phi
-> HOPL_prv A (spall o phi)
| HOPL_SAE phi o q : HOPL_prv A (spall o phi)
-> HOPL_prv A (subst_spec var_type var_prog (q..) phi)
| HOPL_CI phi t o e q : HOPL_prv A (subst_spec var_type (e..) (q..) phi)
-> HOPL_prv A (spholds (cexp t o phi) q e)
| HOPL_CE phi t o e q : HOPL_prv A (spholds (cexp t o phi) q e)
-> HOPL_prv A (subst_spec var_type (e..) (q..) phi)
| HOPL_MI phi e : HOPL_prv A (subst_spec var_type (e..) var_exp phi)
-> HOPL_prv A (after (ret e) phi)
| HOPL_ME phi e1 e2 : HOPL_prv A (after e1 (after e2 (ren_spec id swap id phi)))
-> HOPL_prv A (after (bind e1 e2) phi)
| HOPL_MM phi psi e : HOPL_prv (phi :: map (ren_spec id ↑ id) A) psi
-> HOPL_prv A (after e phi)
-> HOPL_prv A (after e psi)
| HOPL_RED phi e1 e2 : red_prog e1 e2
-> HOPL_prv A (subst_spec var_type (e2..) var_exp phi)
-> HOPL_prv A (subst_spec var_type (e1..) var_exp phi)
| HOPL_CONV phi psi : conv_spec phi psi
-> HOPL_prv A phi
-> HOPL_prv A psi.
Lemma HOPL_weak A A' phi :
HOPL_prv A phi -> incl A A' -> HOPL_prv A' phi.
Proof.
induction 1 in A' |- *; intros HA.
all: try unshelve (solve [econstructor; auto with datatypes]); try now econstructor.
- eapply HOPL_RED; eauto.
- eapply HOPL_CONV; eauto.
Qed.
Lemma HOPL_eq A phi B psi :
HOPL_prv A phi -> A = B -> phi = psi -> HOPL_prv B psi.
Proof.
intros H -> ->. apply H.
Qed.
Lemma HOPL_ren sig1 sig2 sig3 A phi :
HOPL_prv A phi -> HOPL_prv (map (ren_spec sig1 sig2 sig3) A) (ren_spec sig1 sig2 sig3 phi).
Proof.
induction 1 in sig1, sig2, sig3 |- * ; cbn in *.
- constructor. now apply in_map.
- econstructor 2. eauto.
- econstructor 3; eauto.
- econstructor 4. eapply HOPL_eq. 3: reflexivity.
+ apply IHHOPL_prv.
+ rewrite !map_map. apply map_ext. intros psi. now asimpl.
- eapply HOPL_eq. 2: reflexivity.
+ econstructor 5 with (t := t⟨sig1⟩). apply IHHOPL_prv.
+ cbn. now asimpl.
- econstructor 6. eapply HOPL_eq. 3: reflexivity.
+ apply IHHOPL_prv.
+ rewrite !map_map. apply map_ext. intros psi. now asimpl.
- eapply HOPL_eq. 2: reflexivity.
+ econstructor 7 with (e := ren_prog sig1 sig2 e). apply IHHOPL_prv.
+ cbn. now asimpl.
- econstructor 8. eapply HOPL_eq. 3: reflexivity.
+ apply IHHOPL_prv.
+ rewrite !map_map. apply map_ext. intros psi. now asimpl.
- eapply HOPL_eq. 2: reflexivity.
+ econstructor 9 with (q := ren_exp sig1 sig2 sig3 q). apply IHHOPL_prv.
+ cbn. now asimpl.
- econstructor 10. eapply HOPL_eq. 2: reflexivity.
+ apply IHHOPL_prv.
+ now asimpl.
- eapply HOPL_eq. 2: reflexivity.
+ econstructor 11. apply IHHOPL_prv.
+ now asimpl.
- constructor 12. eapply HOPL_eq. 2: reflexivity.
+ apply IHHOPL_prv.
+ now asimpl.
- constructor 13. eapply HOPL_eq. 2: reflexivity.
+ apply IHHOPL_prv.
+ cbn. now asimpl.
- econstructor 14. 2: apply IHHOPL_prv2. eapply HOPL_eq; try apply IHHOPL_prv1.
2: reflexivity. f_equal. rewrite !map_map. apply map_ext. intros phi1. now asimpl.
- eapply HOPL_eq with (phi := subst_spec var_type ((ren_prog sig1 sig2 e1)..) var_exp (ren_spec sig1 (upRen_prog_prog sig2) sig3 phi)).
2: reflexivity. econstructor 15 with (e2 := ren_prog sig1 sig2 e2).
+ now apply red_prog_ren.
+ eapply HOPL_eq. 2: reflexivity. apply IHHOPL_prv. now asimpl.
+ now asimpl.
- econstructor 16; try apply IHHOPL_prv. now apply conv_spec_ren.
Qed.