Rec.Examples.sysf_const_sn
Section 10 Case Study : Strong Normalisation of System F
From mathcomp Require Import ssreflect.all_ssreflect.
Require Import Base.axioms Base.fintype Base.ARS.
Require Import Framework.graded Framework.sysf_types Framework.sysf_const_terms.
Set Implicit Arguments.
Unset Strict Implicit.
Require Import Base.axioms Base.fintype Base.ARS.
Require Import Framework.graded Framework.sysf_types Framework.sysf_const_terms.
Set Implicit Arguments.
Unset Strict Implicit.
The tactic repeatedly rewrites with the lemmas established for traversals and models for the
types and terms of System FCBV.
Local Ltac asimpl :=
repeat progress (cbn; fsimpl; gsimpl; ty_simpl; tm_simpl).
repeat progress (cbn; fsimpl; gsimpl; ty_simpl; tm_simpl).
Inductive step {m n} : tm m n -> tm m n -> Prop :=
| step_beta (A : ty m) (s : tm m n.+1) (t : tm m n) :
step (Tm.app (Tm.lam A s) t) s.[Ty.var, t .: Tm.var]%tm
| step_Beta (A : ty m) (s : tm m.+1 n) :
step (Tm.App (Tm.Lam s) A) s.[A .: Ty.var, Tm.var]%tm
| step_appL s1 s2 t :
step s1 s2 -> step (Tm.app s1 t) (Tm.app s2 t)
| step_appR s t1 t2 :
step t1 t2 -> step (Tm.app s t1) (Tm.app s t2)
| step_abs A s1 s2 :
@step m n.+1 s1 s2 -> step (Tm.lam A s1) (Tm.lam A s2)
| step_tapp A s1 s2 :
step s1 s2 -> step (Tm.App s1 A) (Tm.App s2 A)
| step_tabs s1 s2 :
@step m.+1 n s1 s2 -> step (Tm.Lam s1) (Tm.Lam s2).
Lemma step_ebeta {m n} A s t (u : tm m n) :
u = s.[Ty.var, t .: Tm.var]%tm -> step (Tm.app (Tm.lam A s) t) u.
Proof. move->. exact: step_beta. Qed.
Lemma step_eBeta {m n} A s (t : tm m n) :
t = s.[A .: Ty.var, Tm.var]%tm -> step (Tm.App (Tm.Lam s) A) t.
Proof. move->. exact: step_Beta. Qed.
One-step reduction is compatible with substitution.
Lemma step_inst {m1 m2 n1 n2} (sigma : fin m1 -> ty m2) (tau : fin n1 -> tm m2 n2) s t :
step s t -> step s.[sigma,tau]%tm t.[sigma,tau]%tm.
Proof.
move=> st. elim: st m2 n2 tau sigma => {m1 n1 s t}; asimpl; eauto using @step.
- move=> m1 n1 A s t m2 n2 tau sigma. apply: step_ebeta. by asimpl.
- move=> m1 n1 A s m2 n2 tau sigma. apply: step_eBeta. by asimpl.
Qed.
step s t -> step s.[sigma,tau]%tm t.[sigma,tau]%tm.
Proof.
move=> st. elim: st m2 n2 tau sigma => {m1 n1 s t}; asimpl; eauto using @step.
- move=> m1 n1 A s t m2 n2 tau sigma. apply: step_ebeta. by asimpl.
- move=> m1 n1 A s m2 n2 tau sigma. apply: step_eBeta. by asimpl.
Qed.
Definition red {m n} := star (@step m n).
Definition sred {m n k} (sigma tau : fin m -> tm n k) :=
forall x, @red n k (sigma x) (tau x).
Congruence and compatibility of many-step reduction.
This is necessary to show that beta-reduction entails the correct behaviour (Lemma red_beta).
The proofs are standard.
Lemma red_app {m n} (s1 s2 t1 t2 : tm m n) :
red s1 s2 -> red t1 t2 -> red (Tm.app s1 t1) (Tm.app s2 t2).
Proof.
move=> A B. apply: (star_trans (Tm.app s2 t1)).
- apply: (star_hom (@Tm.app m n^~ t1)) A => x y. exact: step_appL.
- apply: star_hom B => x y. exact: step_appR.
Qed.
Lemma red_abs {m n} A (s1 s2 : tm m n.+1) :
red s1 s2 -> red (Tm.lam A s1) (Tm.lam A s2).
Proof. apply: star_hom => x y. exact: step_abs. Qed.
Lemma red_tapp {m n} A (s1 s2 : tm m n) :
red s1 s2 -> red (Tm.App s1 A) (Tm.App s2 A).
Proof. apply: (star_hom (@Tm.App m n^~A)) => x y. exact: step_tapp. Qed.
Lemma red_tabs {m n} (s1 s2 : tm m.+1 n) :
red s1 s2 -> red (Tm.Lam s1) (Tm.Lam s2).
Proof. apply: star_hom => x y. exact: step_tabs. Qed.
Lemma red_inst {m1 m2 n1 n2} (sigma : fin m1 -> ty m2) (tau : fin n1 -> tm m2 n2) s t :
red s t -> red s.[sigma,tau]%tm t.[sigma,tau]%tm.
Proof. apply: star_hom => x y. exact: step_inst. Qed.
Hint Resolve red_app red_abs red_tapp red_tabs : red_congr.
Lemma red_compat {m1 m2 n1 n2} (sigma : fin m1 -> ty m2) (tau1 tau2 : fin n1 -> tm m2 n2) s :
sred tau1 tau2 -> red s.[sigma,tau1]%tm s.[sigma,tau2]%tm.
Proof.
elim: s m2 n2 sigma tau1 tau2; intros; asimpl; eauto with red_congr.
- apply: red_abs. apply: H. hnf=>/=-[i|]//=. asimpl. rewrite Tm.embed [(_ ◁ (_,_))%tm]Tm.embed.
apply: red_inst. exact: H0.
- apply: red_tabs. apply: H. hnf=>/=i. asimpl. rewrite Tm.embed [(_ ◁ (_,_))%tm]Tm.embed.
apply: red_inst. exact: H0.
- exact: starR.
Qed.
Lemma red_beta {m n} s (t1 t2 : tm m n) :
step t1 t2 -> red s.[Ty.var, t1 .: Tm.var]%tm s.[Ty.var, t2 .: Tm.var]%tm.
Proof. move=> h. apply: red_compat => /=-[i|]/=; [exact: starR|exact: star1]. Qed.
red s1 s2 -> red t1 t2 -> red (Tm.app s1 t1) (Tm.app s2 t2).
Proof.
move=> A B. apply: (star_trans (Tm.app s2 t1)).
- apply: (star_hom (@Tm.app m n^~ t1)) A => x y. exact: step_appL.
- apply: star_hom B => x y. exact: step_appR.
Qed.
Lemma red_abs {m n} A (s1 s2 : tm m n.+1) :
red s1 s2 -> red (Tm.lam A s1) (Tm.lam A s2).
Proof. apply: star_hom => x y. exact: step_abs. Qed.
Lemma red_tapp {m n} A (s1 s2 : tm m n) :
red s1 s2 -> red (Tm.App s1 A) (Tm.App s2 A).
Proof. apply: (star_hom (@Tm.App m n^~A)) => x y. exact: step_tapp. Qed.
Lemma red_tabs {m n} (s1 s2 : tm m.+1 n) :
red s1 s2 -> red (Tm.Lam s1) (Tm.Lam s2).
Proof. apply: star_hom => x y. exact: step_tabs. Qed.
Lemma red_inst {m1 m2 n1 n2} (sigma : fin m1 -> ty m2) (tau : fin n1 -> tm m2 n2) s t :
red s t -> red s.[sigma,tau]%tm t.[sigma,tau]%tm.
Proof. apply: star_hom => x y. exact: step_inst. Qed.
Hint Resolve red_app red_abs red_tapp red_tabs : red_congr.
Lemma red_compat {m1 m2 n1 n2} (sigma : fin m1 -> ty m2) (tau1 tau2 : fin n1 -> tm m2 n2) s :
sred tau1 tau2 -> red s.[sigma,tau1]%tm s.[sigma,tau2]%tm.
Proof.
elim: s m2 n2 sigma tau1 tau2; intros; asimpl; eauto with red_congr.
- apply: red_abs. apply: H. hnf=>/=-[i|]//=. asimpl. rewrite Tm.embed [(_ ◁ (_,_))%tm]Tm.embed.
apply: red_inst. exact: H0.
- apply: red_tabs. apply: H. hnf=>/=i. asimpl. rewrite Tm.embed [(_ ◁ (_,_))%tm]Tm.embed.
apply: red_inst. exact: H0.
- exact: starR.
Qed.
Lemma red_beta {m n} s (t1 t2 : tm m n) :
step t1 t2 -> red s.[Ty.var, t1 .: Tm.var]%tm s.[Ty.var, t2 .: Tm.var]%tm.
Proof. move=> h. apply: red_compat => /=-[i|]/=; [exact: starR|exact: star1]. Qed.
Definition ctx m n := fin n -> ty m.
Inductive has_type {m n} (Gamma : ctx m n) : tm m n -> ty m -> Prop :=
| ty_var (x : fin n) :
has_type Gamma (Tm.var x) (Gamma x)
| ty_abs (A B : ty m) (s : tm m n.+1) :
@has_type m n.+1 (A .: Gamma) s B ->
has_type Gamma (Tm.lam A s) (Ty.arr A B)
| ty_app (A B : ty m) (s t : tm m n) :
has_type Gamma s (Ty.arr A B) ->
has_type Gamma t A ->
has_type Gamma (Tm.app s t) B
| ty_tabs (A : ty m.+1) (s : tm m.+1 n) :
@has_type m.+1 n (Gamma >> Ty.ren shift) s A ->
has_type Gamma (Tm.Lam s) (Ty.all A)
| ty_tapp (A : ty m.+1) (B : ty m) (s : tm m n) :
has_type Gamma s (Ty.all A) ->
has_type Gamma (Tm.App s B) A.[B .: Ty.var]%ty.
Notation sn := (sn (@step _ _)).
Lemma sn_closed {m n} (t s : tm m n) :
sn (Tm.app s t) -> sn s.
Proof. apply: (sn_preimage (h := @Tm.app m n^~t)) => x y. exact: step_appL. Qed.
Lemma sn_tclosed {m n} A (s : tm m n) : sn (Tm.App s A) -> sn s.
Proof. apply: (sn_preimage (h := @Tm.App m n^~A)) => x y. exact: step_tapp. Qed.
Lemma sn_inst {m1 m2 n1 n2} (sigma : fin m1 -> ty m2) (tau : fin n1 -> tm m2 n2) s :
sn s.[sigma,tau]%tm -> sn s.
Proof. apply: sn_preimage. exact: step_inst. Qed.
Lemma sn_closed {m n} (t s : tm m n) :
sn (Tm.app s t) -> sn s.
Proof. apply: (sn_preimage (h := @Tm.app m n^~t)) => x y. exact: step_appL. Qed.
Lemma sn_tclosed {m n} A (s : tm m n) : sn (Tm.App s A) -> sn s.
Proof. apply: (sn_preimage (h := @Tm.App m n^~A)) => x y. exact: step_tapp. Qed.
Lemma sn_inst {m1 m2 n1 n2} (sigma : fin m1 -> ty m2) (tau : fin n1 -> tm m2 n2) s :
sn s.[sigma,tau]%tm -> sn s.
Proof. apply: sn_preimage. exact: step_inst. Qed.
Neutral (Definition 10.1)
Definition neutral {m n} (s : tm m n) : bool :=
match s with
| Tm.lam _ _ | Tm.Lam _ => false
| _ => true
end.
match s with
| Tm.lam _ _ | Tm.Lam _ => false
| _ => true
end.
Reducibility candidates (Definition 10.2)
Record reducible {m n} (P : cand m n) : Prop := {
p_sn : forall s, P s -> sn s;
p_cl : forall s t, P s -> step s t -> P t;
p_nc : forall s, neutral s -> (forall t, step s t -> P t) -> P s
}.
p_sn : forall s, P s -> sn s;
p_cl : forall s t, P s -> step s t -> P t;
p_nc : forall s, neutral s -> (forall t, step s t -> P t) -> P s
}.
Definition admissibility.
S-traversal (Definition 10.3) and S evaluation.
Definition S {m n} : Ty.smodel (cand m n) (cand m n).
Proof.
apply: Ty.SModel.
- exact id.
- intros P Q f. refine (forall s, P s -> Q (Tm.app f s)).
- intros F f. refine (forall P B, reducible P -> F P (Tm.App f B)).
Defined.
Notation E := (Ty.seval S).
Proof.
apply: Ty.SModel.
- exact id.
- intros P Q f. refine (forall s, P s -> Q (Tm.app f s)).
- intros F f. refine (forall P B, reducible P -> F P (Tm.App f B)).
Defined.
Notation E := (Ty.seval S).
Facts about reducible sets.
Lemma reducible_sn {m n} : reducible (sn : tm m n -> Prop).
Proof. constructor; eauto using ARS.sn. by move=> s t [sigma] /sigma. Qed.
Hint Resolve @reducible_sn.
Lemma reducible_const {m n} (P : cand m n) : reducible P -> P (Tm.const m n).
Proof. move/p_nc. apply=> // t st. by inversion st. Qed.
Lemma ad_cons {m n k} (P : cand n k) (rho : fin m -> cand n k) :
reducible P -> admissible rho -> admissible (P .: rho).
Proof. by move=> H1 H2 [i|] //=. Qed.
Lemma 10.4 and consequences.
Lemma L_reducible {m n k} (A : ty m) (rho : fin m -> cand n k) :
admissible rho -> reducible (E rho A).
Proof with eauto using @step.
elim: A n k rho => /={m}[m i|m A ih1 B ih2|m A ih] n k rho safe.
- exact: safe.
- constructor.
+ move=> s. asimpl=> h. apply (@sn_closed n k (Tm.const n k)).
apply: (p_sn (P := E rho B))... apply: h. apply: reducible_const...
+ move=> s t h st u la. apply: (p_cl _ (s := Tm.app s u))...
+ move=> s ns. asimpl=> h t la. have snt := p_sn (ih1 _ _ _ safe) la.
elim: snt la => {t} t _ ih3 la. apply: p_nc...
move=> v st; inversion st; clear st; subst=>//...
apply: ih3 => //. exact: (p_cl (ih1 _ _ _ safe)) la _.
- cbn. constructor.
+ move=> s /(_ sn (Ty.all (Ty.var bound)) reducible_sn)/p_sn/sn_tclosed; apply.
by apply/ih/ad_cons...
+ move=> s t h st P B rep. apply: p_cl (step_tapp B st)...
by apply/ih/ad_cons.
+ move=> s ns h P B rep. apply ih... exact: ad_cons.
move=> t st. inversion st; clear st; subst=> //. exact: h.
Qed.
Corollary L_sn {m n k} A (rho : fin m -> cand n k) s :
admissible rho -> E rho A s -> sn s.
Proof. move/L_reducible/p_sn. apply. Qed.
Corollary L_cl {m n k} T (rho : fin m -> cand n k) s t :
admissible rho -> E rho T s -> step s t -> E rho T t.
Proof. move/L_reducible/p_cl. apply. Qed.
Corollary L_nc {m n k} T (rho : fin m -> cand n k) s :
admissible rho -> neutral s -> (forall t, step s t -> E rho T t) -> E rho T s.
Proof. move/L_reducible/p_nc. apply. Qed.
Corollary L_var {m n k} T (rho : fin m -> cand n k) x :
admissible rho -> E rho T (Tm.var x).
Proof. move/L_nc. apply=> // t st. by inversion st. Qed.
Corollary L_const {m n k} T (rho : fin m -> cand n k) :
admissible rho -> E rho T (Tm.const n k).
Proof. move/L_nc. apply=> // t st. by inversion st. Qed.
Corollary L_cl_star {m n k} T (rho : fin m -> cand n k) s t :
admissible rho -> E rho T s -> red s t -> E rho T t.
Proof. move=> /L_cl cl H st. elim: st H; eauto. Qed.
admissible rho -> reducible (E rho A).
Proof with eauto using @step.
elim: A n k rho => /={m}[m i|m A ih1 B ih2|m A ih] n k rho safe.
- exact: safe.
- constructor.
+ move=> s. asimpl=> h. apply (@sn_closed n k (Tm.const n k)).
apply: (p_sn (P := E rho B))... apply: h. apply: reducible_const...
+ move=> s t h st u la. apply: (p_cl _ (s := Tm.app s u))...
+ move=> s ns. asimpl=> h t la. have snt := p_sn (ih1 _ _ _ safe) la.
elim: snt la => {t} t _ ih3 la. apply: p_nc...
move=> v st; inversion st; clear st; subst=>//...
apply: ih3 => //. exact: (p_cl (ih1 _ _ _ safe)) la _.
- cbn. constructor.
+ move=> s /(_ sn (Ty.all (Ty.var bound)) reducible_sn)/p_sn/sn_tclosed; apply.
by apply/ih/ad_cons...
+ move=> s t h st P B rep. apply: p_cl (step_tapp B st)...
by apply/ih/ad_cons.
+ move=> s ns h P B rep. apply ih... exact: ad_cons.
move=> t st. inversion st; clear st; subst=> //. exact: h.
Qed.
Corollary L_sn {m n k} A (rho : fin m -> cand n k) s :
admissible rho -> E rho A s -> sn s.
Proof. move/L_reducible/p_sn. apply. Qed.
Corollary L_cl {m n k} T (rho : fin m -> cand n k) s t :
admissible rho -> E rho T s -> step s t -> E rho T t.
Proof. move/L_reducible/p_cl. apply. Qed.
Corollary L_nc {m n k} T (rho : fin m -> cand n k) s :
admissible rho -> neutral s -> (forall t, step s t -> E rho T t) -> E rho T s.
Proof. move/L_reducible/p_nc. apply. Qed.
Corollary L_var {m n k} T (rho : fin m -> cand n k) x :
admissible rho -> E rho T (Tm.var x).
Proof. move/L_nc. apply=> // t st. by inversion st. Qed.
Corollary L_const {m n k} T (rho : fin m -> cand n k) :
admissible rho -> E rho T (Tm.const n k).
Proof. move/L_nc. apply=> // t st. by inversion st. Qed.
Corollary L_cl_star {m n k} T (rho : fin m -> cand n k) s t :
admissible rho -> E rho T s -> red s t -> E rho T t.
Proof. move=> /L_cl cl H st. elim: st H; eauto. Qed.
Definition tm_sty {m n} (Gamma : fin n -> ty m) (s : tm m n) (A : ty m) : Prop :=
forall k1 k2 (rho : fin m -> cand k1 k2) theta sigma,
admissible rho -> (forall i, E rho (Gamma i) (sigma i)) -> E rho A s.[theta,sigma]%tm.
The fundamental theorem
Ltac inv H := inversion H; clear H; subst.
Lemma beta_expansion {m n k} A B (rho : fin m -> cand n k) s t :
admissible rho -> sn t -> E rho A s.[Ty.var, t .: Tm.var]%tm ->
E rho A (Tm.app (Tm.lam B s) t).
Proof with eauto.
move=> ad snt h. have sns := sn_inst (L_sn ad h).
elim: sns t snt h => {s} s sns ih1 t. elim=> {t} t snt ih2 h.
apply: L_nc => // u st. inv st => //.
- inv H2. apply: ih1 => //. apply: L_cl ad h _. exact: step_inst.
- apply: ih2 => //. apply: L_cl_star ad h _. exact: red_beta.
Qed.
Lemma inst_expansion {m n k} A B (rho : fin m -> cand n k) s :
admissible rho -> E rho A s.[B .: Ty.var, Tm.var]%tm ->
E rho A (Tm.App (Tm.Lam s) B).
Proof.
move=> ad h. have sns := sn_inst (L_sn ad h). elim: sns h.
move=> {s} s _ ih h. apply: L_nc => // t st. inv st => //.
inv H2 => //. apply: ih => //. apply: L_cl ad h _. exact: step_inst.
Qed.
The fundamental theorem (Theorem 10.6).
Syntactic typing implies semantic typing.
Theorem soundness {m n} (Gamma : fin n -> ty m) s A :
has_type Gamma s A -> tm_sty Gamma s A.
Proof with eauto using L_sn, ad_cons.
elim=> {Gamma s A m n}[m n|m n Gamma A B s _ ih|m n Gamma A B s t _ ih1 _ ih2|m n Gamma A s _ ih|m n Gamma A B s _ /=ih]
k1 k2 rho theta sigma ad el; asimpl...
- move=> t h. apply: beta_expansion... asimpl. apply: ih... by case.
- move: ih1. asimpl. apply=>//. exact: ih2.
- move=> P B h. apply: inst_expansion... asimpl. apply: ih... move=> x.
asimpl. exact: el.
- apply: ih... apply: L_reducible...
Qed.
has_type Gamma s A -> tm_sty Gamma s A.
Proof with eauto using L_sn, ad_cons.
elim=> {Gamma s A m n}[m n|m n Gamma A B s _ ih|m n Gamma A B s t _ ih1 _ ih2|m n Gamma A s _ ih|m n Gamma A B s _ /=ih]
k1 k2 rho theta sigma ad el; asimpl...
- move=> t h. apply: beta_expansion... asimpl. apply: ih... by case.
- move: ih1. asimpl. apply=>//. exact: ih2.
- move=> P B h. apply: inst_expansion... asimpl. apply: ih... move=> x.
asimpl. exact: el.
- apply: ih... apply: L_reducible...
Qed.
Lemma rho_id {m n k} : admissible (fun _ : fin m => sn : tm n k -> Prop).
Proof. move=> x /=. exact: reducible_sn. Qed.
Corollary type_E {m n} Gamma (s : tm m n) A (rho : fin m -> cand m n) :
has_type Gamma s A -> admissible rho -> E rho A s.
Proof.
move=> ty ad. move: (@soundness _ _ Gamma s A ty _ _ rho) => h.
specialize (h Ty.var Tm.var ad). move: h. asimpl. apply=> x /=. exact: L_var.
Qed.
Corollary 10.7