Theory System_F_Subject_Reduction
theory System_F_Subject_Reduction
imports System_F
begin
text ‹
This theory records the independent type-preservation check for the
de Bruijn presentation. It is not needed by the normalization argument,
but it validates the substitution operations used by both beta rules.
›
fun ctx_insert :: "nat ⇒ dty ⇒ dty list ⇒ dty list" where
"ctx_insert i B [] = [B]"
| "ctx_insert 0 B (A # Γ) = B # A # Γ"
| "ctx_insert (Suc i) B (A # Γ) = A # ctx_insert i B Γ"
lemma ctx_insert_Suc_cons:
"ctx_insert (Suc i) B (A # Γ) = A # ctx_insert i B Γ"
by simp
lemma map_ctx_insert:
"map f (ctx_insert i B Γ) = ctx_insert i (f B) (map f Γ)"
proof (induct Γ arbitrary: i)
case Nil
then show ?case by simp
next
case (Cons A Γ)
then show ?case by (cases i) simp_all
qed
lemma ctx_mem_ctx_insert:
assumes "ctx_mem Γ n A"
shows "ctx_mem (ctx_insert i B Γ)
(if n < i then n else Suc n) A"
using assms
proof (induct arbitrary: i B rule: ctx_mem.induct)
case ctx_zero
then show ?case by (cases i) (auto intro: ctx_mem.ctx_zero ctx_mem.ctx_suc)
next
case (ctx_suc Γ n A C)
then show ?case
proof (cases i)
case 0
then show ?thesis
using ctx_suc(1) by (auto intro: ctx_mem.ctx_suc)
next
case (Suc j)
have ih:
"ctx_mem (ctx_insert j B Γ)
(if n < j then n else Suc n) A"
using ctx_suc(2)[of j B] .
from ih Suc show ?thesis
by (cases "n < j") (auto intro: ctx_mem.ctx_suc)
qed
qed
lemma ctx_mem_sucD:
"ctx_mem (B # Γ) (Suc n) A ⟹ ctx_mem Γ n A"
by (erule ctx_mem.cases) simp_all
lemma ctx_mem_insert_cases:
assumes "ctx_mem (ctx_insert i C Γ) n A" "i ≤ length Γ"
shows "(n < i ∧ ctx_mem Γ n A) ∨
(n = i ∧ A = C) ∨
(i < n ∧ ctx_mem Γ (n - 1) A)"
using assms
proof (induct Γ arbitrary: i n C A)
case Nil
then show ?case
by (cases i; cases n; auto elim: ctx_mem.cases)
next
case (Cons D Γ)
then show ?case
proof (cases i)
case 0
have zero: "i = 0" using 0 .
have mem0: "ctx_mem (C # D # Γ) n A"
using Cons.prems(1) zero by simp
then show ?thesis
using mem0 zero
by (cases rule: ctx_mem.cases)
(auto intro: ctx_mem.ctx_zero ctx_mem.ctx_suc)
next
case (Suc j)
have isuc: "i = Suc j" using Suc .
show ?thesis
proof (cases n)
case 0
have nzero: "n = 0" using 0 .
have mem0: "ctx_mem (D # ctx_insert j C Γ) 0 A"
using Cons.prems(1) isuc nzero by simp
then show ?thesis
using mem0 isuc nzero
by (cases rule: ctx_mem.cases)
(auto intro: ctx_mem.ctx_zero ctx_mem.ctx_suc)
next
case (Suc m)
have nsuc: "n = Suc m" using Suc .
have source:
"ctx_mem (D # ctx_insert j C Γ) (Suc m) A"
using Cons.prems(1) isuc nsuc by simp
have mem:
"ctx_mem (ctx_insert j C Γ) m A"
using ctx_mem_sucD[OF source] .
have len: "j ≤ length Γ"
using Cons.prems(2) isuc by simp
have ih:
"(m < j ∧ ctx_mem Γ m A) ∨
(m = j ∧ A = C) ∨
(j < m ∧ ctx_mem Γ (m - 1) A)"
using Cons.hyps[of j C m A] mem len .
have lift:
"j < m ⟹ ctx_mem Γ (m - 1) A ⟹
ctx_mem (D # Γ) m A"
proof -
assume jm: "j < m"
assume mem': "ctx_mem Γ (m - 1) A"
have mpos: "0 < m" using jm by arith
have eq: "m = Suc (m - 1)" using Suc_pred'[OF mpos] .
from ctx_mem.ctx_suc[OF mem'] show ?thesis
using eq by simp
qed
show ?thesis
using ih isuc nsuc
by (auto simp add: ctx_insert.simps
intro: lift
intro: ctx_mem.ctx_zero ctx_mem.ctx_suc)
qed
qed
qed
lemma typing_weakening:
"typing k Γ M A ⟹
typing k (ctx_insert i B Γ) (tm_shift i M) A"
proof (induct arbitrary: i B rule: typing.induct)
case (ty_var Γ n A k)
then show ?case
proof (cases "n < i")
case True
have mem:
"ctx_mem (ctx_insert i B Γ)
(if n < i then n else Suc n) A"
using ctx_mem_ctx_insert[OF ty_var(1)] .
then show ?thesis
using True by (auto intro: typing.ty_var)
next
case False
have mem:
"ctx_mem (ctx_insert i B Γ)
(if n < i then n else Suc n) A"
using ctx_mem_ctx_insert[OF ty_var(1)] .
then show ?thesis
using False by (auto intro: typing.ty_var)
qed
next
case ty_app
then show ?case
unfolding tm_shift.simps
by (blast intro: typing.ty_app)
next
case (ty_lam k0 A0 Γ0 M0 B0)
show ?case
unfolding tm_shift.simps
proof (rule typing.ty_lam)
show "wf_ty k0 A0" using ty_lam(1) .
show "typing k0 (A0 # ctx_insert i B Γ0)
(tm_shift (Suc i) M0) B0"
using ty_lam(3)[of "Suc i" B]
by (simp add: ctx_insert_Suc_cons)
qed
next
case (ty_tabs k0 Γ0 M0 B0)
show ?case
unfolding tm_shift.simps
proof (rule typing.ty_tabs)
have ih:
"typing (Suc k0)
(ctx_insert i (ty_shift 0 B) (map (ty_shift 0) Γ0))
(tm_shift i M0) B0"
using ty_tabs(2)[of i "ty_shift 0 B"] .
then show "typing (Suc k0)
(map (ty_shift 0) (ctx_insert i B Γ0))
(tm_shift i M0) B0"
by (simp add: map_ctx_insert)
qed
next
case (ty_tapp k0 Γ0 M0 B0 A0)
show ?case
unfolding tm_shift.simps
proof (rule typing.ty_tapp)
show "typing k0 (ctx_insert i B Γ0) (tm_shift i M0)
(TyAll B0)"
using ty_tapp(2)[of i B] .
show "wf_ty k0 A0" using ty_tapp(3) .
qed
qed
lemma wf_ty_shift_at:
assumes "wf_ty k A" "l ≤ k"
shows "wf_ty (Suc k) (ty_shift l A)"
using assms
proof (induct arbitrary: l rule: wf_ty.induct)
case (wf_var n k l)
then show ?case
proof (cases "n < l")
case True
have "n < Suc k"
using wf_var.hyps wf_var.prems by arith
have wf: "wf_ty (Suc k) (TyVar n)"
by (rule wf_ty.wf_var) fact
then show ?thesis
using wf by (simp add: ty_shift.simps True)
next
case False
have "Suc n < Suc k"
using wf_var.hyps by simp
have wf: "wf_ty (Suc k) (TyVar (Suc n))"
by (rule wf_ty.wf_var) fact
then show ?thesis
using wf by (simp add: ty_shift.simps False)
qed
next
case (wf_arr k A B l)
then show ?case
by (auto intro: wf_ty.wf_arr)
next
case (wf_all k A l)
then show ?case
by (auto intro: wf_ty.wf_all)
qed
lemma wf_ty_shift:
assumes "wf_ty k A"
shows "wf_ty (Suc k) (ty_shift 0 A)"
using wf_ty_shift_at[OF assms, of 0] by simp
lemma ctx_mem_map:
assumes "ctx_mem Γ n A"
shows "ctx_mem (map f Γ) n (f A)"
using assms
by (induct rule: ctx_mem.induct)
(auto intro: ctx_mem.ctx_zero ctx_mem.ctx_suc)
lemma ty_shift_commute:
assumes "i ≤ j"
shows "ty_shift i (ty_shift j A) =
ty_shift (Suc j) (ty_shift i A)"
using assms
proof (induct A arbitrary: i j)
case (TyVar n i j)
then show ?case
by (cases "n < i"; cases "n < j"; simp_all; arith)
next
case (TyArr A B i j)
then show ?case by simp
next
case (TyAll A i j)
then show ?case
by (simp_all add: ty_shift.simps)
qed
lemma ty_subst_shift:
assumes "l ≤ k"
shows "ty_subst (Suc k) (ty_shift l S) (ty_shift l A) =
ty_shift l (ty_subst k S A)"
using assms
proof (induct A arbitrary: k l S)
case (TyVar n k l S)
then show ?case
by (cases "n < l"; cases "n < k"; cases "n = k";
simp_all split: if_splits; arith)
next
case (TyArr A B k l S)
then show ?case by simp
next
case (TyAll A k l S)
then show ?case
by (simp_all add: ty_shift_commute)
qed
lemma ty_subst_ty_shift:
"ty_subst (Suc k) (ty_shift 0 S) (ty_shift 0 A) =
ty_shift 0 (ty_subst k S A)"
using ty_subst_shift[of 0 k S A] by simp
lemma ty_subst_shift_suc:
assumes "k ≤ l"
shows "ty_subst k (ty_shift l S) (ty_shift (Suc l) A) =
ty_shift l (ty_subst k S A)"
using assms
proof (induct A arbitrary: k l S)
case (TyVar n k l S)
then show ?case
by (cases "n < l"; cases "n < Suc l"; cases "n < k";
cases "n = k"; simp_all split: if_splits; arith)
next
case (TyArr A B k l S)
then show ?case by simp
next
case (TyAll A k l S)
then show ?case
by (simp_all add: ty_shift_commute)
qed
lemma typing_ty_shift_at:
assumes "typing k Γ M A" "l ≤ k"
shows "typing (Suc k) (map (ty_shift l) Γ)
(tm_ty_shift l M) (ty_shift l A)"
using assms
proof (induct arbitrary: l rule: typing.induct)
case (ty_var Γ n A k l)
then show ?case
by (auto intro: typing.ty_var ctx_mem_map)
next
case (ty_app k0 Γ0 M0 A0 B0 N0 l)
have M:
"typing (Suc k0) (map (ty_shift l) Γ0)
(tm_ty_shift l M0) (TyArr (ty_shift l A0) (ty_shift l B0))"
using ty_app(2)[OF ty_app(5)] by (simp add: ty_shift.simps)
have N:
"typing (Suc k0) (map (ty_shift l) Γ0)
(tm_ty_shift l N0) (ty_shift l A0)"
using ty_app(4)[OF ty_app(5)] by simp
show ?case
unfolding tm_ty_shift.simps
using typing.ty_app[OF M N] by simp
next
case (ty_lam k0 A0 Γ0 M0 B0 l)
have wf:
"wf_ty (Suc k0) (ty_shift l A0)"
using wf_ty_shift_at[OF ty_lam(1) ty_lam(4)] by simp
have body:
"typing (Suc k0) (map (ty_shift l) (A0 # Γ0))
(tm_ty_shift l M0) (ty_shift l B0)"
using ty_lam(3)[OF ty_lam(4)] by simp
then show ?case
unfolding tm_ty_shift.simps
using wf by (simp add: typing.ty_lam)
next
case (ty_tabs k0 Γ0 M0 B0 l)
have le: "Suc l ≤ Suc k0"
using ty_tabs(3) by simp
have body:
"typing (Suc (Suc k0))
(map (ty_shift (Suc l)) (map (ty_shift 0) Γ0))
(tm_ty_shift (Suc l) M0) (ty_shift (Suc l) B0)"
using ty_tabs(2)[of "Suc l", OF le] by simp
have shift_comp:
"(ty_shift (Suc l) ∘ ty_shift 0) =
(ty_shift 0 ∘ ty_shift l)"
by (rule ext; simp add: ty_shift_commute)
have body':
"typing (Suc (Suc k0))
(map (ty_shift 0) (map (ty_shift l) Γ0))
(tm_ty_shift (Suc l) M0) (ty_shift (Suc l) B0)"
using body by (simp add: map_map shift_comp)
have tabs:
"typing (Suc k0) (map (ty_shift l) Γ0)
(TmTAbs (tm_ty_shift (Suc l) M0))
(TyAll (ty_shift (Suc l) B0))"
using typing.ty_tabs[OF body'] by simp
then show ?case
by (simp add: tm_ty_shift.simps ty_shift.simps)
next
case (ty_tapp k0 Γ0 M0 B0 A0 l)
have M:
"typing (Suc k0) (map (ty_shift l) Γ0)
(tm_ty_shift l M0) (TyAll (ty_shift (Suc l) B0))"
using ty_tapp(2)[OF ty_tapp(4)] by simp
have W:
"wf_ty (Suc k0) (ty_shift l A0)"
using wf_ty_shift_at[OF ty_tapp(3) ty_tapp(4)] by simp
have inst:
"ty_subst0 (ty_shift l A0) (ty_shift (Suc l) B0) =
ty_shift l (ty_subst0 A0 B0)"
unfolding ty_subst0_def
using ty_subst_shift_suc[of 0 l A0 B0] by simp
have tapp:
"typing (Suc k0) (map (ty_shift l) Γ0)
(TmTApp (tm_ty_shift l M0) (ty_shift l A0))
(ty_subst0 (ty_shift l A0) (ty_shift (Suc l) B0))"
using typing.ty_tapp[OF M W] .
then show ?case
using inst by (simp add: tm_ty_shift.simps)
qed
lemma typing_ty_shift:
"typing k Γ M A ⟹
typing (Suc k) (map (ty_shift 0) Γ)
(tm_ty_shift 0 M) (ty_shift 0 A)"
using typing_ty_shift_at[of k Γ M A 0] by simp
lemma wf_ty_subst_pred:
assumes "wf_ty n A" "wf_ty (n - 1) S" "j < n"
shows "wf_ty (n - 1) (ty_subst j S A)"
using assms
proof (induct arbitrary: S j rule: wf_ty.induct)
case wf_var
then show ?case
by (auto split: if_splits
intro: wf_ty.wf_var)
next
case wf_arr
then show ?case
by (auto intro: wf_ty.wf_arr)
next
case (wf_all k0 A0 S0 j0)
have kpos: "0 < k0"
using wf_all(4) by arith
have shiftS: "wf_ty k0 (ty_shift 0 S0)"
using wf_ty_shift[OF wf_all(3)] by (simp add: kpos)
have inner: "wf_ty k0
(ty_subst (Suc j0) (ty_shift 0 S0) A0)"
using wf_all(2)[of "ty_shift 0 S0" "Suc j0"] shiftS wf_all(4)
by simp
then show ?case
unfolding ty_subst.simps
using inner
by (auto intro: wf_ty.wf_all simp add: kpos)
qed
lemma wf_ty_subst_at:
assumes "wf_ty (Suc k) A" "wf_ty k S" "j ≤ k"
shows "wf_ty k (ty_subst j S A)"
using wf_ty_subst_pred[of "Suc k" A S j] assms by simp
lemma ty_subst_shift_id:
"ty_subst k T (ty_shift k A) = A"
proof (induct A arbitrary: k T)
case (TyVar n k T)
then show ?case
by (cases "n < k"; cases "n = k";
simp_all add: ty_subst.simps ty_shift.simps split: if_splits; arith)
next
case (TyArr A1 A2 k T)
show ?case
unfolding ty_subst.simps ty_shift.simps
using TyArr(1)[of k T] TyArr(2)[of k T] by simp
next
case (TyAll A k T)
show ?case
unfolding ty_subst.simps ty_shift.simps
using TyAll(1)[of "Suc k" "ty_shift 0 T"] by simp
qed
lemma ty_subst_comp_at:
"i ≤ j ⟶
ty_subst i (ty_subst j S T)
(ty_subst (Suc j) (ty_shift i S) A) =
ty_subst j S (ty_subst i T A)"
proof (induct A arbitrary: i j S T rule: dty.induct)
case (TyVar x)
then show ?case
by (intro impI; simp add: ty_subst_shift_id split: if_splits; arith)
next
case (TyArr A1 A2)
then show ?case
by (intro impI; simp_all; blast)
next
case (TyAll A)
have result:
"i ≤ j ⟶
ty_subst (Suc i) (ty_shift 0 (ty_subst j S T))
(ty_subst (Suc (Suc j))
(ty_shift 0 (ty_shift i S)) A) =
ty_subst (Suc j) (ty_shift 0 S)
(ty_subst (Suc i) (ty_shift 0 T) A)"
proof (intro impI)
assume le: "i ≤ j"
have ih:
"ty_subst (Suc i)
(ty_subst (Suc j) (ty_shift 0 S) (ty_shift 0 T))
(ty_subst (Suc (Suc j))
(ty_shift (Suc i) (ty_shift 0 S)) A) =
ty_subst (Suc j) (ty_shift 0 S)
(ty_subst (Suc i) (ty_shift 0 T) A)"
using TyAll(1)[of "Suc i" "Suc j" "ty_shift 0 S" "ty_shift 0 T"]
using le by simp
have comp:
"ty_subst (Suc j) (ty_shift 0 S) (ty_shift 0 T) =
ty_shift 0 (ty_subst j S T)"
using ty_subst_shift[of 0 j S T] by simp
have shift:
"ty_shift (Suc i) (ty_shift 0 S) =
ty_shift 0 (ty_shift i S)"
using ty_shift_commute[of 0 i S] by simp
have ih':
"ty_subst (Suc i)
(ty_subst (Suc j) (ty_shift 0 S) (ty_shift 0 T))
(ty_subst (Suc (Suc j))
(ty_shift 0 (ty_shift i S)) A) =
ty_subst (Suc j) (ty_shift 0 S)
(ty_subst (Suc i) (ty_shift 0 T) A)"
using ih by (simp only: shift[symmetric])
have outer:
"ty_subst (Suc i) (ty_shift 0 (ty_subst j S T))
(ty_subst (Suc (Suc j))
(ty_shift 0 (ty_shift i S)) A) =
ty_subst (Suc i)
(ty_subst (Suc j) (ty_shift 0 S) (ty_shift 0 T))
(ty_subst (Suc (Suc j))
(ty_shift 0 (ty_shift i S)) A)"
by (rule arg_cong[OF comp[symmetric]])
from outer ih' show
"ty_subst (Suc i) (ty_shift 0 (ty_subst j S T))
(ty_subst (Suc (Suc j))
(ty_shift 0 (ty_shift i S)) A) =
ty_subst (Suc j) (ty_shift 0 S)
(ty_subst (Suc i) (ty_shift 0 T) A)"
by simp
qed
then show ?case by simp
qed
lemma ty_subst_comp:
"ty_subst j S (ty_subst 0 T A) =
ty_subst 0 (ty_subst j S T)
(ty_subst (Suc j) (ty_shift 0 S) A)"
using ty_subst_comp_at[of 0 j S T A] by simp
lemma typing_ty_subst_at_aux:
assumes "typing n Γ M A" "n = Suc k" "wf_ty k S" "j ≤ k"
shows "typing k (map (ty_subst j S) Γ)
(tm_ty_subst j S M) (ty_subst j S A)"
using assms
proof (induct arbitrary: k j S rule: typing.induct)
case (ty_var Γ n0 A0 k0 k j S)
then show ?case
by (auto intro: typing.ty_var ctx_mem_map)
next
case (ty_app k0 Γ0 M0 A0 B0 N0 k j S)
have M:
"typing k (map (ty_subst j S) Γ0)
(tm_ty_subst j S M0)
(TyArr (ty_subst j S A0) (ty_subst j S B0))"
using ty_app(2)[OF ty_app(5) ty_app(6) ty_app(7)] by simp
have N:
"typing k (map (ty_subst j S) Γ0)
(tm_ty_subst j S N0) (ty_subst j S A0)"
using ty_app(4)[OF ty_app(5) ty_app(6) ty_app(7)] by simp
show ?case
unfolding tm_ty_subst.simps
using typing.ty_app[OF M N] by simp
next
case (ty_lam k0 A0 Γ0 M0 B0 k j S)
have hA: "wf_ty (Suc k) A0"
using ty_lam(1) ty_lam(4) by simp
have wf:
"wf_ty k (ty_subst j S A0)"
using wf_ty_subst_at[OF hA ty_lam(5) ty_lam(6)] .
have body:
"typing k (map (ty_subst j S) (A0 # Γ0))
(tm_ty_subst j S M0) (ty_subst j S B0)"
using ty_lam(3)[OF ty_lam(4) ty_lam(5) ty_lam(6)] .
have body':
"typing k (ty_subst j S A0 # map (ty_subst j S) Γ0)
(tm_ty_subst j S M0) (ty_subst j S B0)"
using body by simp
have lam:
"typing k (map (ty_subst j S) Γ0)
(TmLam (ty_subst j S A0) (tm_ty_subst j S M0))
(TyArr (ty_subst j S A0) (ty_subst j S B0))"
using typing.ty_lam[OF wf body'] .
show ?case
unfolding tm_ty_subst.simps
using lam by simp
next
case (ty_tabs k0 Γ0 M0 B0 k j S)
have k0_eq: "k0 = Suc k"
using ty_tabs(3) by simp
have le: "Suc j ≤ k0"
using ty_tabs(5) k0_eq by simp
have wfS: "wf_ty k0 (ty_shift 0 S)"
using wf_ty_shift[OF ty_tabs(4)] k0_eq by simp
have body:
"typing k0
(map (ty_subst (Suc j) (ty_shift 0 S))
(map (ty_shift 0) Γ0))
(tm_ty_subst (Suc j) (ty_shift 0 S) M0)
(ty_subst (Suc j) (ty_shift 0 S) B0)"
using ty_tabs(2) wfS le
by simp
have ctx_eq:
"(ty_subst (Suc j) (ty_shift 0 S) ∘ ty_shift 0) =
(ty_shift 0 ∘ ty_subst j S)"
by (rule ext; simp add: ty_subst_ty_shift)
have body':
"typing k0
(map (ty_shift 0) (map (ty_subst j S) Γ0))
(tm_ty_subst (Suc j) (ty_shift 0 S) M0)
(ty_subst (Suc j) (ty_shift 0 S) B0)"
using body by (simp add: map_map ctx_eq)
have tabs:
"typing k (map (ty_subst j S) Γ0)
(TmTAbs (tm_ty_subst (Suc j) (ty_shift 0 S) M0))
(TyAll (ty_subst (Suc j) (ty_shift 0 S) B0))"
using typing.ty_tabs[of k "map (ty_subst j S) Γ0"
"tm_ty_subst (Suc j) (ty_shift 0 S) M0"
"ty_subst (Suc j) (ty_shift 0 S) B0"]
body'
by (simp add: k0_eq)
then show ?case by simp
next
case (ty_tapp k0 Γ0 M0 B0 A0 k j S)
have hA: "wf_ty (Suc k) A0"
using ty_tapp(3) ty_tapp(4) by simp
have M:
"typing k (map (ty_subst j S) Γ0)
(tm_ty_subst j S M0)
(TyAll (ty_subst (Suc j) (ty_shift 0 S) B0))"
using ty_tapp(2)[OF ty_tapp(4) ty_tapp(5) ty_tapp(6)] by simp
have wf:
"wf_ty k (ty_subst j S A0)"
using wf_ty_subst_at[OF hA ty_tapp(5) ty_tapp(6)] .
have tapp:
"typing k (map (ty_subst j S) Γ0)
(TmTApp (tm_ty_subst j S M0) (ty_subst j S A0))
(ty_subst0 (ty_subst j S A0)
(ty_subst (Suc j) (ty_shift 0 S) B0))"
using typing.ty_tapp[OF M wf] .
have result:
"ty_subst j S (ty_subst0 A0 B0) =
ty_subst0 (ty_subst j S A0)
(ty_subst (Suc j) (ty_shift 0 S) B0)"
using ty_subst_comp[of j S A0 B0] by (simp add: ty_subst0_def)
then show ?case
using tapp by (simp add: tm_ty_subst.simps result)
qed
lemma typing_ty_subst_at:
assumes "typing (Suc k) Γ M A" "wf_ty k S" "j ≤ k"
shows "typing k (map (ty_subst j S) Γ)
(tm_ty_subst j S M) (ty_subst j S A)"
proof (rule typing_ty_subst_at_aux[of "Suc k" Γ M A k S j])
show "typing (Suc k) Γ M A" using assms(1) .
show "Suc k = Suc k" by simp
show "wf_ty k S" using assms(2) .
show "j ≤ k" using assms(3) .
qed
lemma typing_ty_subst:
assumes "typing (Suc k) Γ M A" "wf_ty k S"
shows "typing k (map (ty_subst 0 S) Γ)
(tm_ty_subst 0 S M) (ty_subst 0 S A)"
using typing_ty_subst_at[OF assms, of 0] by simp
lemma typing_tm_subst_at:
assumes "typing k Γ N C"
"typing k (ctx_insert i C Γ) M A"
"i ≤ length Γ"
shows "typing k Γ (tm_subst i N M) A"
using assms
proof (induct M arbitrary: k Γ N C i A rule: dtm.induct)
case (TmVar n k Γ N C i A)
have hmem: "ctx_mem (ctx_insert i C Γ) n A"
using TmVar.prems(2)
by (cases rule: typing.cases) auto
have mem:
"(n < i ∧ ctx_mem Γ n A) ∨
(n = i ∧ A = C) ∨
(i < n ∧ ctx_mem Γ (n - 1) A)"
using ctx_mem_insert_cases[OF hmem TmVar.prems(3)] .
show ?case
using mem TmVar.prems(1)
by (auto simp add: tm_subst.simps
intro: typing.ty_var ctx_mem.ctx_zero ctx_mem.ctx_suc)
next
case (TmApp M P k Γ N C i A)
obtain B where
hM: "typing k (ctx_insert i C Γ) M (TyArr B A)" and
hP: "typing k (ctx_insert i C Γ) P B"
using TmApp.prems(2)
by (cases rule: typing.cases) auto
have M:
"typing k Γ
(tm_subst i N M) (TyArr B A)"
using TmApp.hyps(1)[OF TmApp.prems(1) hM TmApp.prems(3)] .
have N':
"typing k Γ (tm_subst i N P) B"
using TmApp.hyps(2)[OF TmApp.prems(1) hP TmApp.prems(3)] .
show ?case
unfolding tm_subst.simps
using typing.ty_app[OF M N'] by simp
next
case (TmLam D M k Γ N C i A)
obtain B where
typeA: "A = TyArr D B" and
wfD: "wf_ty k D" and
hM: "typing k (D # ctx_insert i C Γ) M B"
using TmLam.prems(2)
by (cases rule: typing.cases) auto
have Nshift:
"typing k (D # Γ) (tm_shift 0 N) C"
using typing_weakening[OF TmLam.prems(1), of 0 D]
by (cases Γ; simp)
have len:
"Suc i ≤ length (D # Γ)"
using TmLam.prems(3) by simp
have hM':
"typing k (ctx_insert (Suc i) C (D # Γ)) M B"
using hM by simp
have body:
"typing k (D # Γ)
(tm_subst (Suc i) (tm_shift 0 N) M) B"
using TmLam.hyps[OF Nshift hM' len]
by simp
have lam:
"typing k Γ
(TmLam D (tm_subst (Suc i) (tm_shift 0 N) M))
(TyArr D B)"
using typing.ty_lam[OF wfD body] .
show ?case
unfolding tm_subst.simps
using lam typeA by simp
next
case (TmTAbs M k Γ N C i A)
obtain B where
typeA: "A = TyAll B" and
hM: "typing (Suc k) (map (ty_shift 0) (ctx_insert i C Γ)) M B"
using TmTAbs.prems(2)
by (cases rule: typing.cases) auto
have Nshift:
"typing (Suc k) (map (ty_shift 0) Γ)
(tm_ty_shift 0 N) (ty_shift 0 C)"
using typing_ty_shift[OF TmTAbs.prems(1)] .
have hM':
"typing (Suc k)
(ctx_insert i (ty_shift 0 C) (map (ty_shift 0) Γ)) M B"
using hM by (simp add: map_ctx_insert)
have len:
"i ≤ length (map (ty_shift 0) Γ)"
using TmTAbs.prems(3) by simp
have body:
"typing (Suc k) (map (ty_shift 0) Γ)
(tm_subst i (tm_ty_shift 0 N) M) B"
using TmTAbs.hyps[OF Nshift hM' len] .
have tabs:
"typing k Γ
(TmTAbs (tm_subst i (tm_ty_shift 0 N) M))
(TyAll B)"
using typing.ty_tabs[OF body] .
show ?case
unfolding tm_subst.simps
using tabs typeA by simp
next
case (TmTApp M D k Γ N C i A)
obtain B where
typeA: "A = ty_subst0 D B" and
hM: "typing k (ctx_insert i C Γ) M (TyAll B)" and
wfD: "wf_ty k D"
using TmTApp.prems(2)
by (cases rule: typing.cases) auto
have M:
"typing k Γ (tm_subst i N M) (TyAll B)"
using TmTApp.hyps[OF TmTApp.prems(1) hM TmTApp.prems(3)] .
have tapp:
"typing k Γ
(TmTApp (tm_subst i N M) D)
(ty_subst0 D B)"
using typing.ty_tapp[OF M wfD] .
show ?case
unfolding tm_subst.simps
using tapp typeA by simp
qed
lemma typing_tm_subst0:
assumes "typing k Γ N C"
"typing k (C # Γ) M A"
shows "typing k Γ (tm_subst0 N M) A"
proof -
have major: "typing k (ctx_insert 0 C Γ) M A"
using assms(2) by (cases Γ; simp)
have sub:
"typing k Γ (tm_subst 0 N M) A"
using typing_tm_subst_at[OF assms(1) major] by simp
then show ?thesis
by (simp add: tm_subst0_def)
qed
theorem subject_reduction:
assumes "typing k Γ M A" "M ⟶⇩β M'"
shows "typing k Γ M' A"
using assms(2) assms(1)
proof (induct arbitrary: k Γ A rule: beta.induct)
case (beta_appL M M' N k Γ A)
obtain B where
hM: "typing k Γ M (TyArr B A)" and
hN: "typing k Γ N B"
using beta_appL.prems
by (cases rule: typing.cases) auto
have hM':
"typing k Γ M' (TyArr B A)"
using beta_appL.hyps(2)[OF hM] .
show ?case
using typing.ty_app[OF hM' hN] .
next
case (beta_appR N N' M k Γ A)
obtain B where
hM: "typing k Γ M (TyArr B A)" and
hN: "typing k Γ N (B)"
using beta_appR.prems
by (cases rule: typing.cases) auto
have hN':
"typing k Γ N' B"
using beta_appR.hyps(2)[OF hN] .
show ?case
using typing.ty_app[OF hM hN'] .
next
case (beta_lam M M' D k Γ A)
obtain B where
wfD: "wf_ty k D" and
hM: "typing k (D # Γ) M B" and
typeA: "A = TyArr D B"
using beta_lam.prems
by (cases rule: typing.cases) auto
have hM':
"typing k (D # Γ) M' B"
using beta_lam.hyps(2)[OF hM] .
have lam:
"typing k Γ (TmLam D M') (TyArr D B)"
using typing.ty_lam[OF wfD hM'] .
show ?case
using lam typeA by simp
next
case (beta_tabs M M' k Γ A)
obtain B where
hM: "typing (Suc k) (map (ty_shift 0) Γ) M B" and
typeA: "A = TyAll B"
using beta_tabs.prems
by (cases rule: typing.cases) auto
have hM':
"typing (Suc k) (map (ty_shift 0) Γ) M' B"
using beta_tabs.hyps(2)[OF hM] .
have tabs:
"typing k Γ (TmTAbs M') (TyAll B)"
using typing.ty_tabs[OF hM'] .
show ?case
using tabs typeA by simp
next
case (beta_tapp M M' D k Γ A)
obtain B where
hM: "typing k Γ M (TyAll B)" and
wfD: "wf_ty k D" and
typeA: "A = ty_subst0 D B"
using beta_tapp.prems
by (cases rule: typing.cases) auto
have hM':
"typing k Γ M' (TyAll B)"
using beta_tapp.hyps(2)[OF hM] .
have tapp:
"typing k Γ (TmTApp M' D) (ty_subst0 D B)"
using typing.ty_tapp[OF hM' wfD] .
show ?case
using tapp typeA by simp
next
case (beta_term D M N k Γ A)
obtain B where
hM: "typing k Γ (TmLam D M) (TyArr D B)" and
hN: "typing k Γ N D" and
typeA: "A = B"
using beta_term.prems
by (auto elim: typing.cases)
obtain wfD: "wf_ty k D" and hbody: "typing k (D # Γ) M B"
using hM
by (auto elim: typing.cases)
have sub:
"typing k Γ (tm_subst0 N M) B"
using typing_tm_subst0[OF hN hbody] .
show ?case
using sub typeA by simp
next
case (beta_type M D k Γ A)
obtain B where
hM: "typing k Γ (TmTAbs M) (TyAll B)" and
wfD: "wf_ty k D" and
typeA: "A = ty_subst0 D B"
using beta_type.prems
by (cases rule: typing.cases) auto
obtain hbody where
hbody: "typing (Suc k) (map (ty_shift 0) Γ) M B"
using hM
by (cases rule: typing.cases) auto
have ctx:
"(ty_subst 0 D ∘ ty_shift 0) = id"
by (rule ext; simp add: ty_subst_shift_id)
have sub:
"typing k Γ (tm_ty_subst0 D M) (ty_subst0 D B)"
using typing_ty_subst[OF hbody wfD]
by (simp add: tm_ty_subst0_def ty_subst0_def map_map ctx)
show ?case
using sub typeA by simp
qed
end