(**************************************************************** Copyright © 2014-2024 Amy Felty This file is part of "Two-Level Hybrid in Coq" This program is free software: you can redistribute it and/or modify it under the terms of the GNU General Public License as published by the Free Software Foundation, either version 3 of the License, or (at your option) any later version. This program is distributed in the hope that it will be useful, but WITHOUT ANY WARRANTY; without even the implied warranty of MERCHANTABILITY or FITNESS FOR A PARTICULAR PURPOSE. See the GNU General Public License for more details. You should have received a copy of the GNU General Public License along with this program. If not, see . ***************************************************************) (**************************************************************** File: EqualPolyG.v original: January 2014 Apr 2024: Current Coq Version: V8.18.0 Generalized context version (G version) of: 1. Admissibility of reflexivity of algorithmic equality for the polymorphically typed lambda calculus (types) 2. Admissibility of reflexivity of algorithmic equality for the polymorphically typed lambda calculus (terms) 3. Adequacy ***************************************************************) From HybridSys Require Export sl. #[global] Hint Resolve level_CON level_VAR level_BND level_APP level_ABS : hybrid. #[global] Hint Resolve proper_APP abstr_proper : hybrid. #[global] Hint Unfold proper: hybrid. Section encoding. (**************************************************************** Constants for Lambda Terms ****************************************************************) Inductive Econ: Set := Carr: Econ | Call: Econ | Capp: Econ | Clam: Econ | Ctapp: Econ | Ctlam: Econ. Definition uexp : Set := expr Econ. Definition Var : var -> uexp := (VAR Econ). Definition Bnd : bnd -> uexp := (BND Econ). Definition app : uexp -> uexp -> uexp := fun M1:uexp => fun M2:uexp => (APP (APP (CON Capp) M1) M2). Definition lam : (uexp -> uexp) -> uexp := fun M:uexp->uexp => (APP (CON Clam) (lambda M)). Definition tapp : uexp -> uexp -> uexp := fun M:uexp => fun A:uexp => (APP (APP (CON Ctapp) M) A). Definition tlam : (uexp -> uexp) -> uexp := fun M:uexp->uexp => (APP (CON Ctlam) (lambda M)). Definition arr : uexp -> uexp -> uexp := fun A1:uexp => fun A2:uexp => (APP (APP (CON Carr) A1) A2). Definition all : (uexp -> uexp) -> uexp := fun A:uexp->uexp => (APP (CON Call) (lambda A)). (**************************************************************** Some Properties of Constructors ****************************************************************) Lemma proper_Var: forall x:var, (proper (Var x)). Proof. unfold Var; auto with hybrid. Qed. (**************************************************************** The atm type and instantiation of oo. ****************************************************************) Inductive atm : Set := | tp : uexp -> atm | term : uexp -> atm | atp : uexp -> uexp -> atm | aeq : uexp -> uexp -> atm. Definition oo_ := oo atm Econ. Definition atom_ : atm -> oo_ := atom Econ. Definition T_ : oo_ := T atm Econ. (**************************************************************** Definition of prog ****************************************************************) Inductive prog : atm -> oo_ -> Prop := (* well-formedness of types (arr and all) *) | tp_ar : forall A1 A2:uexp, prog (tp (arr A1 A2)) (Conj (atom_ (tp A1)) (atom_ (tp A2))) | tp_al : forall A:uexp->uexp, abstr A -> prog (tp (all A)) (All (fun a:uexp => (Imp (tp a) (atom_ (tp (A a)))))) (* well-formedness of terms (app, lam, tapp, tlam) *) | tm_a : forall M1 M2:uexp, prog (term (app M1 M2)) (Conj (atom_ (term M1)) (atom_ (term M2))) | tm_l : forall M:uexp->uexp, abstr M -> prog (term (lam M)) (All (fun x:uexp => (Imp (term x) (atom_ (term (M x)))))) | tm_ta : forall M A:uexp, prog (term (tapp M A)) (Conj (atom_ (term M)) (atom_ (tp A))) | tm_tl : forall M:uexp->uexp, abstr M -> prog (term (tlam M)) (All (fun a:uexp => (Imp (tp a) (atom_ (term (M a)))))) (* algorithmic equality for types *) | at_a : forall A1 A2 B1 B2:uexp, prog (atp (arr A1 A2) (arr B1 B2)) (Conj (atom_ (atp A1 B1)) (atom_ (atp A2 B2))) | at_al : forall A B:uexp->uexp, abstr A -> abstr B -> prog (atp (all A) (all B)) (All (fun a:uexp => (Imp (atp a a) (atom_ (atp (A a) (B a)))))) (* algorithmic equality for terms *) | ae_a : forall M1 M2 N1 N2:uexp, prog (aeq (app M1 M2) (app N1 N2)) (Conj (atom_ (aeq M1 N1)) (atom_ (aeq M2 N2))) | ae_l : forall M N:uexp->uexp, abstr M -> abstr N -> prog (aeq (lam M) (lam N)) (All (fun x:uexp => (Imp (aeq x x) (atom_ (aeq (M x) (N x)))))) | ae_ta : forall M N A B:uexp, prog (aeq (tapp M A) (tapp N B)) (Conj (atom_ (aeq M N)) (atom_ (atp A B))) | ae_tl : forall M N:uexp->uexp, abstr M -> abstr N -> prog (aeq (tlam M) (tlam N)) (All (fun a:uexp => (Imp (atp a a) (atom_ (aeq (M a) (N a)))))). Hint Resolve tp_ar tp_al tm_a tm_l tm_ta tm_tl at_a at_al ae_a ae_l ae_ta ae_tl : hybrid. (**************************************************************** Instantiation of seq ****************************************************************) Definition seq_ : nat -> list atm -> oo_ -> Prop := seq prog. Definition seq'_ := seq' prog. Definition seq0 (B : oo_) : Prop := seq'_ nil B. End encoding. #[global] Hint Resolve proper_Var : hybrid. #[global] Hint Resolve tp_ar tp_al tm_a tm_l tm_ta tm_tl at_a at_al ae_a ae_l ae_ta ae_tl : hybrid. #[global] Hint Unfold oo_ atom_ T_: hybrid. #[global] Hint Unfold seq_ seq'_ seq0: hybrid. (**************************************************************** 1. Admissibility of Reflexivity for Types ****************************************************************) (************) (* Contexts *) (************) Section ctx_tp. (* Context Relation for reflexivity of types *) Inductive atpG : list atm -> Prop := | nil_atp : atpG nil | cons_atp : forall (Gamma:list atm) (a:uexp), proper a -> atpG Gamma -> atpG (tp a::atp a a::Gamma). (* Context Membership *) Lemma memb_refl_tp : forall (Gamma:list atm) (T:uexp), atpG Gamma -> (In (tp T) Gamma -> In (atp T T) Gamma). Proof. intros Gamma T; induction 1; try (simpl; tauto). intro h; simpl in h; destruct h as [h | [h | h]]. - injection h; intros; subst; simpl; auto. - discriminate. - simpl; tauto. Qed. Lemma atp_strengthen_weaken : forall (i:nat) (T T':uexp) (Phi Psi:list atm), (forall (T T':uexp), In (atp T T') Phi <-> In (atp T T') Psi) -> seq_ i Phi (atom_ (atp T T')) -> seq_ i Psi (atom_ (atp T T')). Proof. intro i. generalize (lt_wf_ind i (fun i:nat => forall (T T':uexp) (Phi Psi:list atm), (forall (T T':uexp), In (atp T T') Phi <-> In (atp T T') Psi) -> seq_ i Phi (atom_ (atp T T')) -> seq_ i Psi (atom_ (atp T T')))). intro H'. apply H'; clear H' i; auto. intros i h T T' Phi Psi h1 h2. inversion h2; subst; clear h2. - inversion H0; subst; clear H0. (* arr case *) + inversion H3; subst; clear H3. assert (hi:i (Imp (atp a a) (atom_ (atp (A a) (B a)))))); auto with hybrid. apply s_all; auto. intros a h5. generalize (H4 a h5); intro h6. inversion h6; subst; clear h6 H4. apply s_imp; auto. apply h with (atp a a::Phi); auto; try lia. (* proof of extended context inv *) intros T T'; generalize (h1 T T'); simpl; tauto. (* context case *) - destruct (h1 T T') as [h2 h3]. generalize (h2 H2); clear h1 h2 h3 H2. case Psi. + simpl; tauto. + intros a Phi h1. apply s_init; auto with hybrid. Qed. Lemma d_str_alphatp2atp_atp : forall (i:nat) (T T' a:uexp) (Gamma:list atm), seq_ i (tp a::atp a a::Gamma) (atom_ (atp T T')) -> seq_ i (atp a a::Gamma) (atom_ (atp T T')). Proof. intros i T T' a Gamma h. apply atp_strengthen_weaken with (tp a::atp a a::Gamma); auto. clear h T T' i. intros T T'; simpl; split. - intros [h1 | [h1 | h1]]; try discriminate h1; auto. - intros [h1 | h1]; auto. Qed. End ctx_tp. #[global] Hint Resolve nil_atp cons_atp memb_refl_tp : hybrid. (****************************) (* Main Lemmas and Theorems *) (****************************) Section refl_tp. Lemma atp_refl : forall (i:nat) (T:uexp) (Gamma:list atm), atpG Gamma -> seq_ i Gamma (atom_ (tp T)) -> seq_ i Gamma (atom_ (atp T T)). Proof. intro i. generalize (lt_wf_ind i (fun i:nat => forall (T:uexp) (Gamma:list atm), atpG Gamma -> seq_ i Gamma (atom_ (tp T)) -> seq_ i Gamma (atom_ (atp T T)))). intro H'. apply H'; clear H' i; auto. intros i h T Gamma cInv h1. inversion h1; subst; clear h1. - inversion H0; subst; clear H0. (* arr case *) + inversion H3; subst; clear H3. assert (hi:i (Imp (atp a a) (atom_ (atp (A a) (A a)))))); auto with hybrid. apply s_all; auto. intros a h1. generalize (H4 a h1); intro h2. inversion h2; subst; clear h2. apply s_imp; auto. apply d_str_alphatp2atp_atp; auto. apply h; eauto with hybrid; try lia. apply seq_thin_exch with (tp a::Gamma); auto. intro a1; simpl; tauto. (* context case *) - inversion cInv; subst. apply s_init; eauto with hybrid. Qed. Lemma atp_refl_cor : forall (T:uexp), seq0 (atom_ (tp T)) -> seq0 (atom_ (atp T T)). Proof. intros T [n h]. generalize nil_atp; intro h1. specialize atp_refl with (1:=h1) (2:=h); intro h2. exists n; auto. Qed. End refl_tp. (**************************************************************** 2. Admissibility of Reflexivity for Terms ****************************************************************) (************) (* Contexts *) (************) Section ctx_term. (* Context Relation for reflexivity of terms *) Inductive aeqG : list atm -> Prop := | nil_aeq : aeqG nil | tcons_aeq : forall (Gamma:list atm) (a:uexp), proper a -> aeqG Gamma -> aeqG (tp a::atp a a::Gamma) | acons_aeq : forall (Gamma:list atm) (x:uexp), proper x -> aeqG Gamma -> aeqG (term x::aeq x x::Gamma). (* Context Membership *) Lemma memb_refl_term_atp : forall (Gamma:list atm) (T:uexp), aeqG Gamma -> (In (tp T) Gamma -> In (atp T T) Gamma). Proof. intros Gamma T; induction 1; try (simpl; tauto). - intro h; simpl in h; destruct h as [h | [h | h]]; try discriminate; try (simpl; auto). injection h; intros; subst; simpl; auto. - intro h; simpl in h; destruct h as [h | [h | h]]; try discriminate; try (simpl; auto). Qed. Lemma memb_refl_term_aeq : forall (Gamma:list atm) (T:uexp), aeqG Gamma -> (In (term T) Gamma -> In (aeq T T) Gamma). Proof. intros Gamma T; induction 1; try (simpl; tauto). - intro h; simpl in h; destruct h as [h | [h | h]]; try discriminate; try (simpl; auto). - intro h; simpl in h; destruct h as [h | [h | h]]; try discriminate; try (simpl; auto). injection h; intros; subst; simpl; auto. Qed. Lemma aeq_strengthen_weaken : forall (i:nat) (T T':uexp) (Phi Psi:list atm), (forall (T T':uexp), In (aeq T T') Phi <-> In (aeq T T') Psi) -> (forall (T T':uexp), In (atp T T') Phi <-> In (atp T T') Psi) -> seq_ i Phi (atom_ (aeq T T')) -> seq_ i Psi (atom_ (aeq T T')). Proof. intro i. generalize (lt_wf_ind i (fun i:nat => forall (T T':uexp) (Phi Psi:list atm), (forall (T T':uexp), In (aeq T T') Phi <-> In (aeq T T') Psi) -> (forall (T T':uexp), In (atp T T') Phi <-> In (atp T T') Psi) -> seq_ i Phi (atom_ (aeq T T')) -> seq_ i Psi (atom_ (aeq T T')))). intro H'. apply H'; clear H' i; auto. intros i h T T' Phi Psi h1 h1' h2. inversion h2; subst; clear h2. - inversion H0; subst; clear H0. (* app case *) + inversion H3; subst; clear H3. assert (hi:i (Imp (aeq x x) (atom_ (aeq (M x) (N x)))))); auto with hybrid. apply s_all; auto. intros x h5. generalize (H4 x h5); intro h6. inversion h6; subst; clear h6 H4. apply s_imp; auto. apply h with (aeq x x::Phi); auto; try lia. (* proof of extended context inv *) * intros T T'; generalize (h1 T T'); simpl; tauto. * intros T T'; generalize (h1 T T'); generalize (h1' T T'); simpl; tauto. (* tapp case *) + inversion H3; subst; clear H3. assert (hi:i (Imp (atp a a) (atom_ (aeq (M a) (N a)))))); auto with hybrid. apply s_all; auto. intros a h5. generalize (H4 a h5); intro h6. inversion h6; subst; clear h6 H4. apply s_imp; auto. apply h with (atp a a::Phi); auto; try lia. (* proof of extended context inv *) * intros T T'; generalize (h1 T T'); simpl; tauto. * intros T T'; generalize (h1 T T'); generalize (h1' T T'); simpl; tauto. (* context case *) - destruct (h1 T T') as [h2 h3]. generalize (h2 H2); clear h1 h2 h3 H2. case Psi. + simpl; tauto. + intros a Phi h1. apply s_init; auto with hybrid. Qed. Lemma d_str_xa2a_aeq : forall (i:nat) (T T' x:uexp) (Gamma:list atm), seq_ i (term x::aeq x x::Gamma) (atom_ (aeq T T')) -> seq_ i (aeq x x::Gamma) (atom_ (aeq T T')). Proof. intros i T T' x Gamma h. apply aeq_strengthen_weaken with (term x::aeq x x::Gamma); auto. - clear h T T' i. intros T T'; simpl; split. + intros [h1 | [h1 | h1]]; try discriminate h1; auto. + intros [h1 | h1]; auto. - clear h T T' i. intros T T'; simpl; split. + intros [h1 | [h1 | h1]]; try discriminate h1; auto. + intros [h1 | h1]; auto. Qed. Lemma d_str_alphatp2atp_aeq : forall (i:nat) (T T' x:uexp) (Gamma:list atm), seq_ i (tp x::atp x x::Gamma) (atom_ (aeq T T')) -> seq_ i (atp x x::Gamma) (atom_ (aeq T T')). Proof. intros i T T' x Gamma h. apply aeq_strengthen_weaken with (tp x::atp x x::Gamma); auto. - clear h T T' i. intros T T'; simpl; split. + intros [h1 | [h1 | h1]]; try discriminate h1; auto. + intros [h1 | h1]; auto. - clear h T T' i. intros T T'; simpl; split. + intros [h1 | [h1 | h1]]; try discriminate h1; auto. + intros [h1 | h1]; auto. Qed. Lemma tp_strengthen_weaken : forall (i:nat) (T:uexp) (Phi Psi:list atm), (forall (T:uexp), In (tp T) Phi <-> In (tp T) Psi) -> seq_ i Phi (atom_ (tp T)) -> seq_ i Psi (atom_ (tp T)). Proof. intro i. generalize (lt_wf_ind i (fun i:nat => forall (T:uexp) (Phi Psi:list atm), (forall (T:uexp), In (tp T) Phi <-> In (tp T) Psi) -> seq_ i Phi (atom_ (tp T)) -> seq_ i Psi (atom_ (tp T)))). intro H'. apply H'; clear H' i; auto. intros i h T Phi Psi h1 h2. inversion h2; subst; clear h2. - inversion H0; subst; clear H0. (* arr case *) + inversion H3; subst; clear H3. assert (hi:i (Imp (tp x) (atom_ (tp (A x)))))); auto with hybrid. apply s_all; auto. intros x h5. generalize (H4 x h5); intro h6. inversion h6; subst; clear h6 H4. apply s_imp; auto. apply h with (tp x::Phi); auto; try lia. (* proof of extended context inv *) intro T; generalize (h1 T); simpl; tauto. (* context case *) - destruct (h1 T) as [h2 h3]. generalize (h2 H2); clear h1 h2 h3 H2. case Psi. + simpl; tauto. + intros a Phi h1. apply s_init; auto with hybrid. Qed. End ctx_term. #[global] Hint Resolve nil_aeq tcons_aeq acons_aeq : hybrid. (*************) (* Promotion *) (*************) Section promote. Fixpoint rm_aeq2atp (l:list atm) {struct l} : list atm := match l with | (tp x::atp y z::l') => (tp x::atp y z::rm_aeq2atp l') | (term x::aeq y z::l') => (rm_aeq2atp l') | _ => nil end. (* This version works as well: Fixpoint rm_aeq2atp (l:list atm) {struct l} : list atm := match l with nil => nil | (tp x::l') => (tp x::rm_aeq2atp l') | (term x::l') => (rm_aeq2atp l') | (atp x y::l') => (atp x y::rm_aeq2atp l') | (aeq x y::l') => (rm_aeq2atp l') end. *) (* Schema Strengthening *) Lemma aeqG2atpG_strengthen : forall (Gamma:list atm), aeqG Gamma -> atpG (rm_aeq2atp Gamma). Proof. intros Gamma; induction 1; simpl; eauto with hybrid. Qed. Lemma rm_aeq2atp_lem_tp : forall (T:uexp) (Gamma:list atm), aeqG Gamma -> (In (tp T) Gamma <-> In (tp T) (rm_aeq2atp Gamma)). Proof. intros T Gamma; induction 1; try (simpl; tauto). split; try (simpl; tauto). simpl; intros [h1 | [h1 | h1]]; try tauto; try discriminate. Qed. Hint Resolve rm_aeq2atp_lem_tp : hybrid. Lemma c_str_aeq2atp_tp : forall (i:nat) (T:uexp) (Gamma:list atm), aeqG Gamma -> seq_ i Gamma (atom_ (tp T)) -> seq_ i (rm_aeq2atp Gamma) (atom_ (tp T)). Proof. intros i T Gamma h1 h2. apply tp_strengthen_weaken with Gamma; eauto with hybrid. Qed. Lemma rm_aeq2atp_lem_atp : forall (T T':uexp) (Gamma:list atm), aeqG Gamma -> (In (atp T T') (rm_aeq2atp Gamma) <-> In (atp T T') Gamma). Proof. intros T T' Gamma; induction 1; try (simpl; tauto). split; try (simpl; tauto). simpl; intros [h1 | [h1 | h1]]; try tauto; try discriminate. Qed. Hint Resolve rm_aeq2atp_lem_atp : hybrid. Lemma c_wk_aeq2atp_atp : forall (i:nat) (T T':uexp) (Gamma:list atm), aeqG Gamma -> seq_ i (rm_aeq2atp Gamma) (atom_ (atp T T')) -> seq_ i Gamma (atom_ (atp T T')). Proof. intros i T T' Gamma h1 h2. apply atp_strengthen_weaken with (rm_aeq2atp Gamma); eauto with hybrid. Qed. Hint Resolve c_wk_aeq2atp_atp c_str_aeq2atp_tp aeqG2atpG_strengthen : hybrid. Hint Resolve atp_refl : hybrid. (* Promotion Lemma for Reflexivity of Types *) Lemma afp_refl_promote : forall (i:nat) (A:uexp) (Gamma:list atm), aeqG Gamma -> seq_ i Gamma (atom_ (tp A)) -> seq_ i Gamma (atom_ (atp A A)). Proof. intros i A Gamma h h2; eauto with hybrid. (* apply c_wk_aeq2atp_atp; auto. apply atp_refl; auto. apply aeqG2atpG_strengthen; auto. apply c_str_aeq2atp_tp; auto. *) Qed. End promote. #[global] Hint Resolve memb_refl_term_atp memb_refl_term_aeq : hybrid. (****************************) (* Main Lemmas and Theorems *) (****************************) Section refl_term. Lemma aeq_refl : forall (i:nat) (T:uexp) (Gamma:list atm), aeqG Gamma -> seq_ i Gamma (atom_ (term T)) -> seq_ i Gamma (atom_ (aeq T T)). Proof. intro i. generalize (lt_wf_ind i (fun i:nat => forall (T:uexp) (Gamma:list atm), aeqG Gamma -> seq_ i Gamma (atom_ (term T)) -> seq_ i Gamma (atom_ (aeq T T)))). intro H'. apply H'; clear H' i; auto. intros i h T Gamma cInv h1. inversion h1; subst; clear h1. - inversion H0; subst; clear H0. (* app case *) + inversion H3; subst; clear H3. assert (hi:i (Imp (aeq x x) (atom_ (aeq (M x) (M x)))))); auto with hybrid. apply s_all; auto. intros x h1. generalize (H4 x h1); intro h2. inversion h2; subst; clear h2. apply s_imp; auto. apply d_str_xa2a_aeq; auto. apply h; eauto with hybrid; try lia. apply seq_thin_exch with (term x::Gamma); auto. intro a; simpl; tauto. (* tapp case *) + inversion H3; subst; clear H3. assert (hi:i (Imp (atp a a) (atom_ (aeq (M a) (M a)))))); auto with hybrid. apply s_all; auto. intros a h1. generalize (H4 a h1); intro h2. inversion h2; subst; clear h2. apply s_imp; auto. apply d_str_alphatp2atp_aeq; auto. apply h; eauto with hybrid; try lia. apply seq_thin_exch with (tp a::Gamma); auto. intro a1; simpl; tauto. (* context case *) - inversion cInv; subst. + apply s_init; eauto with hybrid. + apply s_init; eauto with hybrid. Qed. Lemma aeq_refl_cor : forall (T:uexp), seq0 (atom_ (term T)) -> seq0 (atom_ (aeq T T)). Proof. intros T [n h]. generalize nil_aeq; intro h1. specialize aeq_refl with (1:=h1) (2:=h); intro h2. exists n; auto. Qed. End refl_term. (**************************************************************** 3. Adequacy ****************************************************************) (************************) (* Inversion Properties *) (************************) (* Specialized inversion properties of prog (could be automated) *) Section atp_inv. Lemma at_al_inv : forall (i:nat) (Phi:list atm) (T T':uexp->uexp), (forall x : uexp, proper x -> seq_ i Phi (Imp (atp x x) (atom_ (atp (T x) (T' x))))) -> exists j:nat, (i=j+1 /\ forall x : uexp, proper x -> seq_ j (atp x x::Phi) (atom_ (atp (T x) (T' x)))). Proof. induction i; auto. - intros Phi T T' H. generalize (H (Var 0) (proper_Var 0)); intro H1. inversion H1; clear H1; subst. replace (i+1) with (S i) in H0; try lia. - intros Phi T T' H. exists i; split; try lia. intros x H0. generalize (H x H0); intro H1. inversion H1; clear H1; subst. assert (i0 = i); try lia. subst; auto. Qed. End atp_inv. (************) (* Contexts *) (************) Section ctx_atp_adeq. (* Membership lemma used in adequacy of atp *) Lemma memb_atp_adeq1 : forall (Gamma:list atm) (T T':uexp), atpG Gamma -> In (atp T T') Gamma -> In (tp T) Gamma. Proof. intros Gamma T; induction 1; try (simpl; tauto). intro h; simpl in h; destruct h as [h | [h | h]]; try discriminate; try (simpl; auto). injection h; intros; subst; subst; simpl; auto. Qed. Lemma memb_atp_adeq2 : forall (Gamma:list atm) (T T':uexp), atpG Gamma -> In (atp T T') Gamma -> In (tp T') Gamma. Proof. intros Gamma T; induction 1; try (simpl; tauto). intro h; simpl in h; destruct h as [h | [h | h]]; try discriminate; try (simpl; auto). injection h; intros; subst; subst; simpl; auto. Qed. Lemma term_strengthen_weaken : forall (i:nat) (T:uexp) (Phi Psi:list atm), (forall (T:uexp), In (term T) Phi <-> In (term T) Psi) -> (forall (T:uexp), In (tp T) Phi <-> In (tp T) Psi) -> seq_ i Phi (atom_ (term T)) -> seq_ i Psi (atom_ (term T)). Proof. intro i. generalize (lt_wf_ind i (fun i:nat => forall (T:uexp) (Phi Psi:list atm), (forall (T:uexp), In (term T) Phi <-> In (term T) Psi) -> (forall (T:uexp), In (tp T) Phi <-> In (tp T) Psi) -> seq_ i Phi (atom_ (term T)) -> seq_ i Psi (atom_ (term T)))). intro H'. apply H'; clear H' i; auto. intros i h T Phi Psi h1 h1' h2. inversion h2; subst; clear h2. - inversion H0; subst; clear H0. (* app case *) + inversion H3; subst; clear H3. assert (hi:i (Imp (term x) (atom_ (term (M x)))))); auto with hybrid. apply s_all; auto. intros x h5. generalize (H4 x h5); intro h6. inversion h6; subst; clear h6 H4. apply s_imp; auto. apply h with (term x::Phi); auto; try lia. (* proof of extended context inv *) * intro T; generalize (h1 T); simpl; tauto. * intro T; generalize (h1 T); generalize (h1' T); simpl; tauto. (* tapp case *) + inversion H3; subst; clear H3. assert (hi:i (Imp (tp x) (atom_ (term (M x)))))); auto with hybrid. apply s_all; auto. intros x h5. generalize (H4 x h5); intro h6. inversion h6; subst; clear h6 H4. apply s_imp; auto. apply h with (tp x::Phi); auto; try lia. (* proof of extended context inv *) * intro T; generalize (h1 T); simpl; tauto. * intro T; generalize (h1 T); generalize (h1' T); simpl; tauto. (* context case *) - destruct (h1 T) as [h2 h3]. generalize (h2 H2); clear h1 h2 h3 H2. case Psi. + simpl; tauto. + intros a Phi h1. apply s_init; auto with hybrid. Qed. Lemma d_str_alphatp2alph_tp : forall (i:nat) (T T' a:uexp) (Gamma:list atm), seq_ i (tp a::atp a a::Gamma) (atom_ (tp T)) -> seq_ i (tp a::Gamma) (atom_ (tp T)). Proof. intros i T T' a Gamma h. apply tp_strengthen_weaken with (tp a::atp a a::Gamma); auto. clear h T T' i. intro T; simpl; split. - intros [h1 | [h1 | h1]]; try discriminate h1; auto. - intros [h1 | h1]; auto. Qed. End ctx_atp_adeq. #[global] Hint Resolve nil_atp cons_atp memb_atp_adeq1 memb_atp_adeq2 : hybrid. (****************) (* atp Adequacy *) (****************) Section atp_adeq. Lemma atp_tp : forall (i:nat) (T T':uexp) (Gamma:list atm), atpG Gamma -> seq_ i Gamma (atom_ (atp T T')) -> seq_ i Gamma (atom_ (tp T)) /\ seq_ i Gamma (atom_ (tp T')). Proof. intro i. generalize (lt_wf_ind i (fun i:nat => forall (T T':uexp) (Gamma:list atm), atpG Gamma -> seq_ i Gamma (atom_ (atp T T')) -> seq_ i Gamma (atom_ (tp T)) /\ seq_ i Gamma (atom_ (tp T')))). intro H'. apply H'; clear H' i; auto. intros i h T T' Gamma cInv h1. inversion h1; subst; clear h1. - inversion H0; subst; clear H0. (* arr case *) + inversion H3; subst; clear H3. assert (hi:i (seq_ j (tp a::atp a a::Gamma) (atom_ (tp (A a))) /\ seq_ j (tp a::atp a a::Gamma) (atom_ (tp (B a))))). { intros a h1. apply h; eauto with hybrid; try lia. apply seq_thin_exch with (atp a a::Gamma); simpl; auto. apply h2; auto. } split. * unfold seq_,atom_; apply s_bc with (All (fun a:uexp => (Imp (tp a) (atom_ (tp (A a)))))); auto with hybrid. apply s_all; auto. intros a h5. apply s_imp; auto. apply d_str_alphatp2alph_tp; auto. generalize (h' a h5); tauto. * unfold seq_,atom_; apply s_bc with (All (fun a:uexp => (Imp (tp a) (atom_ (tp (B a)))))); auto with hybrid. apply s_all; auto. intros a h5. apply s_imp; auto. apply d_str_alphatp2alph_tp; auto. generalize (h' a h5); tauto. (* context case *) - inversion cInv; subst. split; apply s_init; eauto with hybrid. Qed. Lemma atp_tp1 : forall (i:nat) (T T':uexp) (Gamma:list atm), atpG Gamma -> seq_ i Gamma (atom_ (atp T T')) -> seq_ i Gamma (atom_ (tp T)). Proof. apply atp_tp. Qed. Lemma atp_tp2 : forall (i:nat) (T T':uexp) (Gamma:list atm), atpG Gamma -> seq_ i Gamma (atom_ (atp T T')) -> seq_ i Gamma (atom_ (tp T')). Proof. apply atp_tp. Qed. Lemma atp_tp_cor : forall T T':uexp, seq0 (atom_ (atp T T')) -> (seq0 (atom_ (tp T)) /\ seq0 (atom_ (tp T'))). Proof. intros T T' [n h]. generalize nil_atp; intro h1. specialize atp_tp with (1:=h1) (2:=h); intros [h2 h3]. split; exists n; auto. Qed. End atp_adeq. (*************) (* Promotion *) (*************) Section promote_atp_adeq. Lemma c_str_aeq2atp_atp : forall (i:nat) (T T':uexp) (Gamma:list atm), aeqG Gamma -> seq_ i Gamma (atom_ (atp T T')) -> seq_ i (rm_aeq2atp Gamma) (atom_ (atp T T')). Proof. intros i T T' Gamma h1 h2. apply atp_strengthen_weaken with Gamma; eauto with hybrid. intros T1 T2; rewrite <- rm_aeq2atp_lem_atp; eauto with hybrid; tauto. (* "Hint Resolve rm_aeq2atp_lem_atp" would work except that <-> is in the wrong direction *) Qed. Lemma c_wk_aeq2atp_tp : forall (i:nat) (T:uexp) (Gamma:list atm), aeqG Gamma -> seq_ i (rm_aeq2atp Gamma) (atom_ (tp T)) -> seq_ i Gamma (atom_ (tp T)). Proof. intros i T Gamma h1 h2. apply tp_strengthen_weaken with (rm_aeq2atp Gamma); eauto with hybrid. intro T'; rewrite <- rm_aeq2atp_lem_tp; eauto with hybrid; tauto. (* "Hint Resolve rm_aeq2atp_lem_tp" would work except that <-> is in the wrong direction *) Qed. Hint Resolve c_wk_aeq2atp_tp c_str_aeq2atp_atp aeqG2atpG_strengthen : hybrid. Hint Resolve atp_tp1 atp_tp2 : hybrid. (* Promotion Lemma for Adequacy of atp *) Lemma atp_tp_promote : forall (i:nat) (T T':uexp) (Gamma:list atm), aeqG Gamma -> seq_ i Gamma (atom_ (atp T T')) -> seq_ i Gamma (atom_ (tp T)) /\ seq_ i Gamma (atom_ (tp T')). Proof. intros i T T' Gamma h h2; split; eauto with hybrid. (* apply c_wk_aeq2atp_tp; auto. apply atp_tp1 with T'; auto. apply aeqG2atpG_strengthen; auto. apply c_str_aeq2atp_atp; auto. apply c_wk_aeq2atp_tp; auto. apply atp_tp2 with T; auto. apply aeqG2atpG_strengthen; auto. apply c_str_aeq2atp_atp; auto. *) Qed. End promote_atp_adeq. (************************) (* Inversion Properties *) (************************) (* Specialized inversion properties of prog (could be automated) *) Section aeq_inv. Lemma ae_l_inv : forall (i:nat) (Phi:list atm) (T T':uexp->uexp), (forall x : uexp, proper x -> seq_ i Phi (Imp (aeq x x) (atom_ (aeq (T x) (T' x))))) -> exists j:nat, (i=j+1 /\ forall x : uexp, proper x -> seq_ j (aeq x x::Phi) (atom_ (aeq (T x) (T' x)))). Proof. induction i; auto. - intros Phi T T' H. generalize (H (Var 0) (proper_Var 0)); intro H1. inversion H1; clear H1; subst. replace (i+1) with (S i) in H0; try lia. - intros Phi T T' H. exists i; split; try lia. intros x H0. generalize (H x H0); intro H1. inversion H1; clear H1; subst. assert (i0 = i); try lia. subst; auto. Qed. Lemma ae_tl_inv : forall (i:nat) (Phi:list atm) (M N:uexp->uexp), (forall a : uexp, proper a -> seq_ i Phi (Imp (atp a a) (atom_ (aeq (M a) (N a))))) -> exists j:nat, (i=j+1 /\ forall a : uexp, proper a -> seq_ j (atp a a::Phi) (atom_ (aeq (M a) (N a)))). Proof. induction i; auto. - intros Phi M N H. generalize (H (Var 0) (proper_Var 0)); intro H1. inversion H1; clear H1; subst. replace (i+1) with (S i) in H0; try lia. - intros Phi M N H. exists i; split; try lia. intros a H0. generalize (H a H0); intro H1. inversion H1; clear H1; subst. assert (i0 = i); try lia. subst; auto. Qed. End aeq_inv. (************) (* Contexts *) (************) Section ctx_aeq_adeq. (* Membership lemmas used in adequacy of aeq *) Lemma memb_aeq_adeq1 : forall (Gamma:list atm) (T T':uexp), aeqG Gamma -> In (aeq T T') Gamma -> In (term T) Gamma. Proof. intros Gamma T; induction 1; try (simpl; tauto). - intro h; simpl in h; destruct h as [h | [h | h]]; try discriminate; try (simpl; tauto). - intro h; simpl in h; destruct h as [h | [h | h]]; try discriminate; try (simpl; tauto). injection h; intros; subst; subst; simpl; auto. Qed. Lemma memb_aeq_adeq2 : forall (Gamma:list atm) (T T':uexp), aeqG Gamma -> In (aeq T T') Gamma -> In (term T') Gamma. Proof. intros Gamma T; induction 1; try (simpl; tauto). - intro h; simpl in h; destruct h as [h | [h | h]]; try discriminate; try (simpl; tauto). - intro h; simpl in h; destruct h as [h | [h | h]]; try discriminate; try (simpl; tauto). injection h; intros; subst; subst; simpl; auto. Qed. Lemma d_str_termaeq2term_term : forall (i:nat) (T x:uexp) (Gamma:list atm), seq_ i (term x::aeq x x::Gamma) (atom_ (term T)) -> seq_ i (term x::Gamma) (atom_ (term T)). Proof. intros i T x Gamma h. apply term_strengthen_weaken with (term x::aeq x x::Gamma); auto. - clear h T i. intro T; simpl; split. + intros [h1 | [h1 | h1]]; try discriminate h1; auto. + intros [h1 | h1]; auto. - clear h T i. intro T; simpl; split. + intros [h1 | [h1 | h1]]; try discriminate h1; auto. + intros [h1 | h1]; auto. Qed. Lemma d_str_alphatp2alph_term : forall (i:nat) (T x:uexp) (Gamma:list atm), seq_ i (tp x::atp x x::Gamma) (atom_ (term T)) -> seq_ i (tp x::Gamma) (atom_ (term T)). Proof. intros i T x Gamma h. apply term_strengthen_weaken with (tp x::atp x x::Gamma); auto. - clear h T i. intro T; simpl; split. + intros [h1 | [h1 | h1]]; try discriminate h1; auto. + intros [h1 | h1]; auto. - clear h T i. intro T; simpl; split. * intros [h1 | [h1 | h1]]; try discriminate h1; auto. * intros [h1 | h1]; auto. Qed. End ctx_aeq_adeq. #[global] Hint Resolve nil_aeq tcons_aeq acons_aeq memb_aeq_adeq1 memb_aeq_adeq2 : hybrid. (****************) (* aeq Adequacy *) (****************) Section aeq_adeq. Lemma aeq_term : forall (i:nat) (T T':uexp) (Gamma:list atm), aeqG Gamma -> seq_ i Gamma (atom_ (aeq T T')) -> seq_ i Gamma (atom_ (term T)) /\ seq_ i Gamma (atom_ (term T')). Proof. intro i. generalize (lt_wf_ind i (fun i:nat => forall (T T':uexp) (Gamma:list atm), aeqG Gamma -> seq_ i Gamma (atom_ (aeq T T')) -> seq_ i Gamma (atom_ (term T)) /\ seq_ i Gamma (atom_ (term T')))). intro H'. apply H'; clear H' i; auto. intros i h T T' Gamma cInv h1. inversion h1; subst; clear h1. - inversion H0; subst; clear H0. (* app case *) + inversion H3; subst; clear H3. assert (hi:i (seq_ j (term x::aeq x x::Gamma) (atom_ (term (M x))) /\ seq_ j (term x::aeq x x::Gamma) (atom_ (term (N x))))). { intros x h1. apply h; eauto with hybrid; try lia. apply seq_thin_exch with (aeq x x::Gamma); simpl; auto. apply h2; auto. } split. * unfold seq_,atom_; apply s_bc with (All (fun x:uexp => (Imp (term x) (atom_ (term (M x)))))); auto with hybrid. apply s_all; auto. intros x h5. apply s_imp; auto. apply d_str_termaeq2term_term; auto. generalize (h' x h5); tauto. * unfold seq_,atom_; apply s_bc with (All (fun x:uexp => (Imp (term x) (atom_ (term (N x)))))); auto with hybrid. apply s_all; auto. intros x h5. apply s_imp; auto. apply d_str_termaeq2term_term; auto. generalize (h' x h5); tauto. (* tapp case *) + inversion H3; subst; clear H3. assert (hi:i (seq_ j (tp a::atp a a::Gamma) (atom_ (term (M a))) /\ seq_ j (tp a::atp a a::Gamma) (atom_ (term (N a))))). { intros a h1. apply h; eauto with hybrid; try lia. apply seq_thin_exch with (atp a a::Gamma); simpl; auto. apply h2; auto. } split. * unfold seq_,atom_; apply s_bc with (All (fun a:uexp => (Imp (tp a) (atom_ (term (M a)))))); auto with hybrid. apply s_all; auto. intros a h5. apply s_imp; auto. apply d_str_alphatp2alph_term; auto. generalize (h' a h5); tauto. * unfold seq_,atom_; apply s_bc with (All (fun a:uexp => (Imp (tp a) (atom_ (term (N a)))))); auto with hybrid. apply s_all; auto. intros a h5. apply s_imp; auto. apply d_str_alphatp2alph_term; auto. generalize (h' a h5); tauto. (* context case *) - inversion cInv; subst. + split; apply s_init; eauto with hybrid. (* applied memb_aeq_adeq1 and memb_aeq_adeq2 *) + split; apply s_init; eauto with hybrid. (* applied memb_aeq_adeq1 and memb_aeq_adeq2 *) Qed. Lemma aeq_term_cor : forall T T':uexp, seq0 (atom_ (aeq T T')) -> (seq0 (atom_ (term T)) /\ seq0 (atom_ (term T'))). Proof. intros T T' [n h]. generalize nil_aeq; intro h1. specialize aeq_term with (1:=h1) (2:=h); intros [h2 h3]. split; exists n; auto. Qed. End aeq_adeq.