Theory System_F_Normalization
theory System_F_Normalization
imports System_F_Erasure
begin
definition f_env_ok :: "(nat ⇒ ulam set) ⇒ bool" where
"f_env_ok ρ ⟷ (∀k. ucandidate (ρ k))"
definition f_all_sem :: "(ulam set ⇒ ulam set) ⇒ ulam set" where
"f_all_sem F = {M. ∀C. ucandidate C ⟶ M ∈ F C}"
lemma f_all_candidate:
assumes H: "∀C. ucandidate C ⟶ ucandidate (F C)"
shows "ucandidate (f_all_sem F)"
proof (unfold ucandidate_def, intro conjI)
show "uCR1 (f_all_sem F)"
unfolding uCR1_def f_all_sem_def
using H uSN_set_candidate
unfolding ucandidate_def uCR1_def
by blast
next
show "uCR2 (f_all_sem F)"
unfolding uCR2_def f_all_sem_def
using H
unfolding ucandidate_def uCR2_def
by blast
next
show "uCR3 (f_all_sem F)"
unfolding uCR3_def f_all_sem_def
using H
unfolding ucandidate_def uCR3_def
by blast
qed
definition f_env_insert ::
"nat ⇒ ulam set ⇒ (nat ⇒ ulam set) ⇒
nat ⇒ ulam set"
where
"f_env_insert k C ρ n =
(if n < k then ρ n else
if n = k then C else ρ (n - 1))"
lemma f_env_insert_zero:
"f_env_insert 0 C ρ = ty_env_cons C ρ"
proof (rule ext)
fix x
show "f_env_insert 0 C ρ x = ty_env_cons C ρ x"
proof (cases x)
case 0
then show ?thesis
by (simp add: f_env_insert_def ty_env_cons_def)
next
case (Suc n)
then show ?thesis
by (simp add: f_env_insert_def ty_env_cons_def split: if_splits)
qed
qed
lemma f_env_insert_suc_cons:
"f_env_insert (Suc k) C (ty_env_cons D ρ) =
ty_env_cons D (f_env_insert k C ρ)"
proof (rule ext)
fix x
show "f_env_insert (Suc k) C (ty_env_cons D ρ) x =
ty_env_cons D (f_env_insert k C ρ) x"
proof (induct x)
case 0
then show ?case
by (simp add: f_env_insert_def ty_env_cons_def)
next
case (Suc n)
then show ?case
proof (cases n)
case 0
then show ?thesis
by (simp add: f_env_insert_def ty_env_cons_def)
next
case (Suc m)
then show ?thesis
by (simp add: f_env_insert_def ty_env_cons_def
split: if_splits; arith)
qed
qed
qed
lemma f_env_ok_cons:
assumes "f_env_ok ρ" and "ucandidate C"
shows "f_env_ok (ty_env_cons C ρ)"
using assms
unfolding f_env_ok_def ty_env_cons_def
by (intro allI; case_tac k; simp_all)
fun f_sem :: "dty ⇒ (nat ⇒ ulam set) ⇒ ulam set" where
"f_sem (TyVar k) ρ = ρ k"
| "f_sem (TyArr A B) ρ =
uarr (f_sem A ρ) (f_sem B ρ)"
| "f_sem (TyAll A) ρ =
f_all_sem (λC. f_sem A (ty_env_cons C ρ))"
lemma f_sem_candidate:
"f_env_ok ρ ⟶ ucandidate (f_sem A ρ)"
proof (induct A arbitrary: ρ)
case (TyVar k)
then show ?case
unfolding f_sem.simps f_env_ok_def ucandidate_def by blast
next
case (TyArr A B)
then show ?case
by (auto intro: uarr_candidate)
next
case (TyAll A)
have body:
"f_env_ok ρ ⟶
(∀C. ucandidate C ⟶
ucandidate (f_sem A (ty_env_cons C ρ)))"
using TyAll(1)
by (blast intro: f_env_ok_cons)
then show ?case
unfolding f_sem.simps
by (intro impI; blast intro: f_all_candidate)
qed
lemma f_sem_ty_shift:
"f_sem (ty_shift k A) (f_env_insert k C ρ) =
f_sem A ρ"
proof (induct A arbitrary: k C ρ)
case (TyVar n)
then show ?case
by (simp add: f_env_insert_def split: if_splits; arith)
next
case (TyArr A B)
then show ?case by simp
next
case (TyAll A)
have body_eq:
"∀D. f_sem (ty_shift (Suc k) A)
(ty_env_cons D (f_env_insert k C ρ)) =
f_sem A (ty_env_cons D ρ)"
using TyAll(1)
by (simp add: f_env_insert_suc_cons[symmetric])
show ?case
using body_eq
by (simp add: f_all_sem_def)
qed
lemma f_sem_ty_subst:
"f_sem (ty_subst k S A) ρ =
f_sem A (f_env_insert k (f_sem S ρ) ρ)"
proof (induct A arbitrary: k S ρ)
case (TyVar n)
then show ?case
by (simp add: f_env_insert_def split: if_splits; arith)
next
case (TyArr A B)
then show ?case by simp
next
case (TyAll A)
have shift0:
"∀D. f_sem (ty_shift 0 S) (ty_env_cons D ρ) =
f_sem S ρ"
using f_sem_ty_shift[of 0 S] f_env_insert_zero by simp
have body_eq:
"∀D. f_sem (ty_subst (Suc k) (ty_shift 0 S) A)
(ty_env_cons D ρ) =
f_sem A
(ty_env_cons D (f_env_insert k (f_sem S ρ) ρ))"
using TyAll(1)
by (simp add: shift0 f_sem_ty_shift f_env_insert_zero
f_env_insert_suc_cons)
show ?case
using body_eq
by (simp add: f_all_sem_def)
qed
definition f_tenv_cons :: "ulam ⇒ (nat ⇒ ulam) ⇒
nat ⇒ ulam"
where
"f_tenv_cons N η n =
(case n of 0 ⇒ N | Suc k ⇒ η k)"
definition f_tenv_shift :: "(nat ⇒ ulam) ⇒ nat ⇒ ulam"
where
"f_tenv_shift η n =
(case n of 0 ⇒ UVar 0 | Suc k ⇒ u_shift 0 (η k))"
definition f_env_subst ::
"nat ⇒ ulam ⇒ (nat ⇒ ulam) ⇒
nat ⇒ ulam"
where
"f_env_subst k N η n = u_subst k N (η n)"
lemma f_env_subst_shift:
"f_env_subst (Suc k) (u_shift 0 N) (f_tenv_shift η) =
f_tenv_shift (f_env_subst k N η)"
proof (rule ext)
fix n
show "f_env_subst (Suc k) (u_shift 0 N) (f_tenv_shift η) n =
f_tenv_shift (f_env_subst k N η) n"
proof (induct n)
case 0
then show ?case
by (simp add: f_env_subst_def f_tenv_shift_def)
next
case (Suc n)
then show ?case
by (simp add: f_env_subst_def f_tenv_shift_def
u_shift_subst_comm)
qed
qed
lemma f_env_subst_shift0:
"f_env_subst 0 N (f_tenv_shift η) =
f_tenv_cons N η"
proof (rule ext)
fix n
show "f_env_subst 0 N (f_tenv_shift η) n =
f_tenv_cons N η n"
proof (induct n)
case 0
then show ?case
by (simp add: f_env_subst_def f_tenv_shift_def f_tenv_cons_def
u_subst0_def)
next
case (Suc n)
then show ?case
by (simp add: f_env_subst_def f_tenv_shift_def f_tenv_cons_def
u_subst0_def u_subst_shift)
qed
qed
fun f_interp :: "(nat ⇒ ulam) ⇒ dtm ⇒ ulam" where
"f_interp η (TmVar n) = η n"
| "f_interp η (TmApp M N) =
UApp (f_interp η M) (f_interp η N)"
| "f_interp η (TmLam A M) =
ULam (f_interp (f_tenv_shift η) M)"
| "f_interp η (TmTAbs M) = f_interp η M"
| "f_interp η (TmTApp M A) = f_interp η M"
lemma f_interp_subst:
"u_subst k N (f_interp η M) =
f_interp (f_env_subst k N η) M"
proof (induct M arbitrary: k N η rule: dtm.induct)
case (TmVar n)
then show ?case by (simp add: f_env_subst_def)
next
case (TmApp M P)
then show ?case by simp
next
case (TmLam A M)
then show ?case
by (simp add: f_env_subst_shift)
next
case (TmTAbs M)
then show ?case by simp
next
case (TmTApp M A)
then show ?case by simp
qed
lemma f_tenv_shift_id:
"f_tenv_shift (λn. UVar n) = (λn. UVar n)"
proof (rule ext)
fix x :: nat
show "f_tenv_shift (λn. UVar n) x = UVar x"
proof (induct x)
case 0
then show ?case by (simp add: f_tenv_shift_def)
next
case (Suc n)
then show ?case by (simp add: f_tenv_shift_def)
qed
qed
lemma f_interp_id:
"f_interp (λn. UVar n) M = f_erase M"
by (induct M rule: dtm.induct)
(simp_all add: f_tenv_shift_id)
lemma f_interp_subst0_shift:
"u_subst0 N (f_interp (f_tenv_shift η) M) =
f_interp (f_tenv_cons N η) M"
using f_interp_subst[of 0 N "f_tenv_shift η" M]
f_env_subst_shift0
by (simp add: u_subst0_def)
definition f_tenv_ok ::
"dty list ⇒ (nat ⇒ ulam) ⇒
(nat ⇒ ulam set) ⇒ bool"
where
"f_tenv_ok Γ η ρ ⟷
(∀n A. ctx_mem Γ n A ⟶
η n ∈ f_sem A ρ)"
lemma f_ctx_mem_mapE:
"ctx_mem (map (ty_shift 0) Γ) n B ⟶
(∃A. ctx_mem Γ n A ∧ B = ty_shift 0 A)"
proof (induct Γ arbitrary: n B)
case Nil
then show ?case by (auto elim: ctx_mem.cases)
next
case (Cons A Γ)
then show ?case
proof (intro impI)
assume h: "ctx_mem (map (ty_shift 0) (A # Γ)) n B"
have h': "ctx_mem (ty_shift 0 A # map (ty_shift 0) Γ) n B"
using h by simp
then show "∃A'. ctx_mem (A # Γ) n A' ∧
B = ty_shift 0 A'"
proof (cases rule: ctx_mem.cases)
case ctx_zero
then show ?thesis
by (auto intro: ctx_mem.ctx_zero)
next
case ctx_suc
have h'':
"ctx_mem (map (ty_shift 0) Γ) (n - 1) B"
using ctx_suc(1) ctx_suc(2) by simp
have ex:
"∃A'. ctx_mem Γ (n - 1) A' ∧
B = ty_shift 0 A'"
using Cons(1)[of "n - 1" B] h'' by blast
have ex':
"∃A'. ctx_mem (A # Γ) (Suc (n - 1)) A' ∧
B = ty_shift 0 A'"
using ex by (blast intro: ctx_mem.ctx_suc)
from ex' ctx_suc(1) show ?thesis by simp
qed
qed
qed
lemma f_tenv_ok_cons:
assumes hctx: "f_tenv_ok Γ η ρ"
and hval: "N ∈ f_sem A ρ"
shows "f_tenv_ok (A # Γ) (f_tenv_cons N η) ρ"
using assms
unfolding f_tenv_ok_def
by (auto simp add: f_tenv_cons_def elim: ctx_mem.cases)
lemma f_tenv_ok_ty_shift:
assumes hctx: "f_tenv_ok Γ η ρ"
and henv: "f_env_ok ρ"
and hcan: "ucandidate C"
shows "f_tenv_ok (map (ty_shift 0) Γ) η
(ty_env_cons C ρ)"
proof (unfold f_tenv_ok_def, intro allI allI impI)
fix n B
assume memB: "ctx_mem (map (ty_shift 0) Γ) n B"
have ex:
"∃A. ctx_mem Γ n A ∧ B = ty_shift 0 A"
using f_ctx_mem_mapE[of Γ n B] memB by blast
have sh:
"∀A. f_sem (ty_shift 0 A) (ty_env_cons C ρ) =
f_sem A ρ"
using f_sem_ty_shift[of 0] f_env_insert_zero by simp
have sem:
"∀A. ctx_mem Γ n A ⟶
η n ∈ f_sem (ty_shift 0 A) (ty_env_cons C ρ)"
using hctx sh unfolding f_tenv_ok_def by blast
from ex sem show "η n ∈ f_sem B (ty_env_cons C ρ)"
by blast
qed
definition f_prop ::
"dty list ⇒ dtm ⇒ dty ⇒ bool"
where
"f_prop Γ M A ⟷
(∀ρ η.
f_env_ok ρ ⟶
f_tenv_ok Γ η ρ ⟶
f_interp η M ∈ f_sem A ρ)"
lemma f_fundamental:
"typing k Γ M A ⟹ f_prop Γ M A"
proof (induct rule: typing.induct)
case ty_var
then show ?case
unfolding f_prop_def f_interp.simps f_sem.simps f_tenv_ok_def
by blast
next
case ty_app
then show ?case
unfolding f_prop_def f_interp.simps f_sem.simps uarr_def
by blast
next
case (ty_lam k0 A0 G0 M0 B0)
show ?case
unfolding f_prop_def f_interp.simps f_sem.simps
proof (intro allI allI impI impI)
fix ρ η
assume env: "f_env_ok ρ"
assume ctx: "f_tenv_ok G0 η ρ"
have Ccan: "ucandidate (f_sem A0 ρ)"
using f_sem_candidate[of ρ A0] env by blast
have Dcan: "ucandidate (f_sem B0 ρ)"
using f_sem_candidate[of ρ B0] env by blast
have body:
"∀s. s ∈ f_sem A0 ρ ⟶
u_subst0 s (f_interp (f_tenv_shift η) M0) ∈ f_sem B0 ρ"
proof (intro allI impI)
fix s
assume sA: "s ∈ f_sem A0 ρ"
have ctxs:
"f_tenv_ok (A0 # G0) (f_tenv_cons s η) ρ"
using f_tenv_ok_cons[OF ctx sA] .
have ih:
"f_interp (f_tenv_cons s η) M0 ∈ f_sem B0 ρ"
using ty_lam(3) env ctxs
unfolding f_prop_def by blast
have eq:
"u_subst0 s (f_interp (f_tenv_shift η) M0) =
f_interp (f_tenv_cons s η) M0"
using f_interp_subst0_shift by blast
from ih show
"u_subst0 s (f_interp (f_tenv_shift η) M0) ∈ f_sem B0 ρ"
using eq by simp
qed
have abs:
"ULam (f_interp (f_tenv_shift η) M0) ∈
uarr (f_sem A0 ρ) (f_sem B0 ρ)"
using Ccan Dcan body by (rule uabs_RED)
then show "ULam (f_interp (f_tenv_shift η) M0) ∈
uarr (f_sem A0 ρ) (f_sem B0 ρ)" .
qed
next
case (ty_tabs k0 G0 M0 B0)
show ?case
unfolding f_prop_def
proof (intro allI allI impI impI)
fix ρ η
assume env: "f_env_ok ρ"
assume ctx: "f_tenv_ok G0 η ρ"
have all:
"∀C. ucandidate C ⟶
f_interp η M0 ∈ f_sem B0 (ty_env_cons C ρ)"
proof (intro allI impI)
fix C
assume Ccan: "ucandidate C"
have envC: "f_env_ok (ty_env_cons C ρ)"
using f_env_ok_cons[OF env Ccan] .
have ctxC:
"f_tenv_ok (map (ty_shift 0) G0) η
(ty_env_cons C ρ)"
using f_tenv_ok_ty_shift[OF ctx env Ccan] .
have ih:
"f_interp η M0 ∈ f_sem B0 (ty_env_cons C ρ)"
using ty_tabs(2) envC ctxC
unfolding f_prop_def by blast
from ih show "f_interp η M0 ∈ f_sem B0 (ty_env_cons C ρ)"
by assumption
qed
show "f_interp η (TmTAbs M0) ∈ f_sem (TyAll B0) ρ"
using all unfolding f_interp.simps f_sem.simps f_all_sem_def by blast
qed
next
case (ty_tapp k0 G0 M0 B0 A0)
show ?case
unfolding f_prop_def
proof (intro allI allI impI impI)
fix ρ η
assume env: "f_env_ok ρ"
assume ctx: "f_tenv_ok G0 η ρ"
have ih:
"f_interp η M0 ∈ f_sem (TyAll B0) ρ"
using ty_tapp(2) env ctx
unfolding f_prop_def by blast
have Acan: "ucandidate (f_sem A0 ρ)"
using f_sem_candidate[of ρ A0] env by blast
have body:
"f_interp η M0 ∈
f_sem B0 (ty_env_cons (f_sem A0 ρ) ρ)"
using ih Acan unfolding f_sem.simps f_all_sem_def by blast
have sem_eq:
"f_sem (ty_subst0 A0 B0) ρ =
f_sem B0 (ty_env_cons (f_sem A0 ρ) ρ)"
using f_sem_ty_subst[of 0 A0 B0 ρ] f_env_insert_zero
by (simp add: ty_subst0_def)
show "f_interp η (TmTApp M0 A0) ∈
f_sem (ty_subst0 A0 B0) ρ"
using body sem_eq by simp
qed
qed
lemma f_identity_tenv_ok:
"f_tenv_ok Γ (λn. UVar n) (λ_. uSN_set)"
proof (unfold f_tenv_ok_def, intro allI allI impI)
fix n A
assume "ctx_mem Γ n A"
have can:
"ucandidate (f_sem A (λ_. uSN_set))"
using f_sem_candidate[of "(λ_. uSN_set)" A]
by (simp add: f_env_ok_def uSN_set_candidate)
from uvar_mem_candidate[OF can]
show "UVar n ∈ f_sem A (λ_. uSN_set)" .
qed
lemma f_welltyped_fundamental:
assumes "typing k Γ M A"
shows "uSN (f_erase M)"
proof -
have env: "f_env_ok (λ_. uSN_set)"
unfolding f_env_ok_def
by (simp add: uSN_set_candidate)
have ctx:
"f_tenv_ok Γ (λn. UVar n) (λ_. uSN_set)"
using f_identity_tenv_ok .
have sem:
"f_interp (λn. UVar n) M ∈
f_sem A (λ_. uSN_set)"
using f_fundamental[OF assms] env ctx
unfolding f_prop_def by blast
have semM:
"f_erase M ∈ f_sem A (λ_. uSN_set)"
using sem f_interp_id by simp
have can:
"ucandidate (f_sem A (λ_. uSN_set))"
using f_sem_candidate[of "(λ_. uSN_set)" A] env by blast
from can semM show "uSN (f_erase M)"
unfolding ucandidate_def uCR1_def by blast
qed
theorem strong_normalization:
assumes "typing k Γ M A"
shows "SN M"
using fSN_reflect[OF f_welltyped_fundamental[OF assms]] .
end