Theory MLSS_Typing
theory MLSS_Typing
imports MLSS_Calculus
begin
section ‹Typing and Branch Expansion›
text ‹
In this theory, we prove that the branch expansion rules
preserve well-typedness.
›
context includes no member_ASCII_syntax
begin
lemma types_term_unique:
shows "v ⊢ t : l1 ⟹ v ⊢ t : l2 ⟹ l2 = l1"
apply(induction arbitrary: l2 rule: types_pset_term.induct)
apply (metis types_pset_term_cases)+
done
lemma type_of_term_if_types_term:
shows "v ⊢ t : l ⟹ type_of_term v t = l"
using types_term_unique unfolding type_of_term_def by blast
lemma types_term_if_mem_subterms_term:
assumes "s ∈ subterms t"
assumes "v ⊢ t : lt"
shows "∃ls. v ⊢ s : ls"
using assms
by (induction t arbitrary: s lt) (auto elim: types_pset_term_cases)
lemma is_Var_if_types_term_0:
shows "v ⊢ t : 0 ⟹ is_Var t"
by (induction t) (auto elim: types_pset_term_cases)
lemma is_Var_if_urelem': "urelem' v φ t ⟹ is_Var t"
using is_Var_if_types_term_0 by blast
lemma is_Var_if_urelem: "urelem φ t ⟹ is_Var t"
unfolding urelem_def using is_Var_if_urelem' by blast
lemma types_fmD:
"v ⊢ And p q ⟹ v ⊢ p"
"v ⊢ And p q ⟹ v ⊢ q"
"v ⊢ Or p q ⟹ v ⊢ p"
"v ⊢ Or p q ⟹ v ⊢ q"
"v ⊢ Neg p ⟹ v ⊢ p"
"v ⊢ Atom a ⟹ v ⊢ a"
unfolding types_pset_fm_def using fm.set_intros by auto
lemma types_fmI:
"v ⊢ p ⟹ v ⊢ q ⟹ v ⊢ And p q"
"v ⊢ p ⟹ v ⊢ q ⟹ v ⊢ Or p q"
"v ⊢ p ⟹ v ⊢ Neg p"
"v ⊢ a ⟹ v ⊢ Atom a"
unfolding types_pset_fm_def using fm.set_intros by auto
lemma types_pset_atom_Member_D:
includes no member_ASCII_syntax
assumes "v ⊢ s ∈⇩s f t1 t2" "f ∈ {(⊔⇩s), (⊓⇩s), (-⇩s)}"
shows "v ⊢ s ∈⇩s t1" "v ⊢ s ∈⇩s t2"
proof -
from assms obtain ls where
"v ⊢ s : ls" "v ⊢ f t1 t2 : Suc ls"
using types_pset_atom.simps by fastforce
with assms have "v ⊢ s ∈⇩s t1 ∧ v ⊢ s ∈⇩s t2"
by (auto simp: types_pset_atom.simps elim: types_pset_term_cases)
then show "v ⊢ s ∈⇩s t1" "v ⊢ s ∈⇩s t2"
by blast+
qed
lemmas types_pset_atom_Member_Union_D = types_pset_atom_Member_D[where ?f="(⊔⇩s)", simplified]
and types_pset_atom_Member_Inter_D = types_pset_atom_Member_D[where ?f="(⊓⇩s)", simplified]
and types_pset_atom_Member_Diff_D = types_pset_atom_Member_D[where ?f="(-⇩s)", simplified]
lemma types_term_if_mem_subterms:
includes no member_ASCII_syntax
fixes φ :: "'a pset_fm"
assumes "v ⊢ φ"
assumes "f t1 t2 ∈ subterms φ" "f ∈ {(⊔⇩s), (⊓⇩s), (-⇩s)}"
obtains lt where "v ⊢ t1 : lt" "v ⊢ t2 : lt"
proof -
from assms obtain a :: "'a pset_atom" where atom: "v ⊢ a" "f t1 t2 ∈ subterms a"
unfolding types_pset_fm_def by (induction φ) auto
obtain t' l where "v ⊢ t' : l" "f t1 t2 ∈ subterms t'"
apply(rule types_pset_atom.cases[OF ‹v ⊢ a›])
using atom(2) by auto
then obtain lt where "v ⊢ t1 : lt ∧ v ⊢ t2 : lt"
by (induction t' arbitrary: l)
(use assms(3) in ‹auto elim: types_pset_term_cases›)
with that show ?thesis
by blast
qed
lemma types_if_types_Member_and_subterms:
fixes φ :: "'a pset_fm"
assumes "v ⊢ s ∈⇩s t1 ∨ v ⊢ s ∈⇩s t2" "v ⊢ φ"
assumes "f t1 t2 ∈ subterms φ" "f ∈ {(⊔⇩s), (⊓⇩s), (-⇩s)}"
shows "v ⊢ s ∈⇩s f t1 t2"
proof -
from types_term_if_mem_subterms[OF assms(2-)] obtain lt where lt:
"v ⊢ t1 : lt" "v ⊢ t2 : lt"
by blast
moreover from assms(1) lt(1,2) obtain ls where "v ⊢ s : ls" "lt = Suc ls"
by (auto simp: types_pset_atom.simps dest: types_term_unique)
ultimately show ?thesis
using assms
by (auto simp: types_pset_term.intros types_pset_atom.simps)
qed
lemma types_subst_tlvl:
includes no member_ASCII_syntax
fixes l :: "'a pset_atom"
assumes "v ⊢ AT (t1 =⇩s t2)" "v ⊢ l"
shows "v ⊢ subst_tlvl t1 t2 l"
proof -
from assms obtain lt where "v ⊢ t1 : lt" "v ⊢ t2 : lt"
by (auto simp: types_pset_atom.simps dest!: types_fmD(6))
with assms(2) show ?thesis
by (cases "(t1, t2, l)" rule: subst_tlvl.cases)
(auto simp: types_pset_atom.simps dest: types_term_unique)
qed
lemma types_sym_Equal:
assumes "v ⊢ t1 =⇩s t2"
shows "v ⊢ t2 =⇩s t1"
using assms by (auto simp: types_pset_atom.simps)
lemma types_lexpands:
fixes φ :: "'a pset_fm"
assumes "lexpands b' b" "b ≠ []" "φ ∈ set b'"
assumes "⋀(φ :: 'a pset_fm). φ ∈ set b ⟹ v ⊢ φ"
shows "v ⊢ φ"
using assms
proof(induction rule: lexpands.induct)
case (1 b' b)
then show ?case
apply(induction rule: lexpands_fm.induct)
apply(force dest: types_fmD intro: types_fmI(3))+
done
next
case (2 b' b)
then show ?case
proof(induction rule: lexpands_un.induct)
case (1 s t1 t2 b)
then show ?thesis
by (auto dest!: types_fmD(5,6) "1"(4) intro!: types_fmI(2,3,4)
intro: types_pset_atom_Member_Union_D)
next
case (2 s t1 b t2)
then have "v ⊢ last b"
by auto
from types_if_types_Member_and_subterms[OF _ this] 2 show ?case
by (auto dest!: "2"(5) types_fmD(6) intro: types_fmI(4))
next
case (3 s t2 b t1)
then have "v ⊢ last b"
by auto
from types_if_types_Member_and_subterms[OF _ this] 3 show ?case
by (auto dest!: "3"(5) types_fmD(6) intro: types_fmI(4))
next
case (4 s t1 t2 b)
then show ?case
by (auto dest!: types_fmD(5,6) "4"(5) intro!: types_fmI(2,3,4)
intro: types_pset_atom_Member_Union_D)
next
case (5 s t1 t2 b)
then show ?case
by (auto dest!: types_fmD(5,6) "5"(5) intro!: types_fmI(2,3,4)
intro: types_pset_atom_Member_Union_D)
next
case (6 s t1 b t2)
then have "v ⊢ last b"
by auto
note types_if_types_Member_and_subterms[where ?f="(⊔⇩s)", OF _ this "6"(3), simplified]
with 6 show ?case
by (auto dest!: types_fmD(5,6) "6"(6) intro!: types_fmI(2,3,4))
qed
next
case (3 b' b)
then show ?case
proof(induction rule: lexpands_int.induct)
case (1 s t1 t2 b)
then show ?thesis
by (auto dest!: types_fmD(5,6) "1"(4) intro!: types_fmI(2,3,4)
intro: types_pset_atom_Member_Inter_D)
next
case (2 s t1 b t2)
then have "v ⊢ last b"
by auto
from types_if_types_Member_and_subterms[OF _ this] 2 show ?case
by (auto dest!: "2"(5) types_fmD(5,6) intro!: types_fmI(3,4))
next
case (3 s t2 b t1)
then have "v ⊢ last b"
by auto
from types_if_types_Member_and_subterms[OF _ this] 3 show ?case
by (auto dest!: "3"(5) types_fmD(5,6) intro!: types_fmI(3,4))
next
case (4 s t1 t2 b)
then show ?case
by (auto dest!: types_fmD(5,6) "4"(5) intro!: types_fmI(2,3,4)
intro: types_pset_atom_Member_Inter_D)
next
case (5 s t1 t2 b)
then show ?case
by (auto dest!: types_fmD(5,6) "5"(5) intro!: types_fmI(2,3,4)
intro: types_pset_atom_Member_Inter_D)
next
case (6 s t1 b t2)
then have "v ⊢ last b"
by auto
note types_if_types_Member_and_subterms[where ?f="(⊓⇩s)", OF _ this "6"(3), simplified]
with 6 show ?case
by (auto dest!: types_fmD(5,6) "6"(6) intro!: types_fmI(2,3,4))
qed
next
case (4 b' b)
then show ?case
proof(induction rule: lexpands_diff.induct)
case (1 s t1 t2 b)
then show ?thesis
by (auto dest!: types_fmD(5,6) "1"(4) intro!: types_fmI(2,3,4)
intro: types_pset_atom_Member_Diff_D)
next
case (2 s t1 b t2)
then have "v ⊢ last b"
by auto
from types_if_types_Member_and_subterms[OF _ this] 2 show ?case
by (auto dest!: "2"(5) types_fmD(5,6) intro!: types_fmI(3,4))
next
case (3 s t2 b t1)
then have "v ⊢ last b"
by auto
from types_if_types_Member_and_subterms[OF _ this] 3 show ?case
by (auto dest!: "3"(5) types_fmD(5,6) intro!: types_fmI(3,4))
next
case (4 s t1 t2 b)
then show ?case
by (auto dest!: types_fmD(5,6) "4"(5) intro!: types_fmI(2,3,4)
intro: types_pset_atom_Member_Diff_D)
next
case (5 s t1 t2 b)
then show ?case
by (auto dest!: types_fmD(5,6) "5"(5) intro!: types_fmI(2,3,4)
intro: types_pset_atom_Member_Diff_D)
next
case (6 s t1 b t2)
then have "v ⊢ last b"
by auto
note types_if_types_Member_and_subterms[where ?f="(-⇩s)", OF _ this "6"(3), simplified]
with 6 show ?case
by (auto dest!: types_fmD(5,6) "6"(6) intro!: types_fmI(2,3,4))
qed
next
case (5 b' b)
then show ?case
proof(cases rule: lexpands_single.cases)
case (1 t1)
with 5 have "v ⊢ last b"
by auto
with ‹Single t1 ∈ subterms (last b)› obtain a :: "'a pset_atom"
where atom: "a ∈ atoms (last b)" "Single t1 ∈ subterms a" "v ⊢ a"
unfolding types_pset_fm_def by (metis UN_E subterms_fm_def)
obtain t' l where "Single t1 ∈ subterms t'" "v ⊢ t' : l"
apply(rule types_pset_atom.cases[OF ‹v ⊢ a›])
using atom(2) by auto
note types_term_if_mem_subterms_term[OF this]
then obtain lt1 where "v ⊢ t1 : lt1" "v ⊢ Single t1 : Suc lt1"
by (metis types_pset_term_cases(3))
with 5 1 show ?thesis
using types_pset_atom.intros(2) types_pset_fm_def by fastforce
qed (auto simp: types_pset_atom.simps elim!: types_pset_term_cases
dest!: types_fmD(5,6) "5"(4) intro!: types_fmI(3,4))
next
case (6 b' b)
then show ?case
proof(cases rule: lexpands_eq.cases)
case (5 s t s')
with 6 show ?thesis
by (auto 0 3 dest!: "6"(4) types_fmD(5,6) dest: types_term_unique
simp: types_pset_atom.simps types_term_unique intro!: types_fmI(3,4))
qed (auto simp: types_sym_Equal dest!: "6"(4) types_fmD(5,6)
intro!: types_fmI(3,4) types_subst_tlvl)
qed
lemma types_bexpands_nowit:
fixes φ :: "'a pset_fm"
assumes "bexpands_nowit bs' b" "b' ∈ bs'" "φ ∈ set b'"
assumes "⋀(φ :: 'a pset_fm). φ ∈ set b ⟹ v ⊢ φ"
shows "v ⊢ φ"
using assms(1)
proof(cases rule: bexpands_nowit.cases)
case (1 p q)
from assms "1"(2) show ?thesis
unfolding "1"(1)
by (auto dest!: assms(4) types_fmD(3) intro!: types_fmI(3))
next
case (2 p q)
from assms "2"(2) show ?thesis
unfolding "2"(1)
by (auto dest!: assms(4) types_fmD(5) dest: types_fmD(1,2) intro!: types_fmI(3))
next
case (3 s t1 t2)
from assms "3"(2,3) show ?thesis
unfolding "3"(1) using types_pset_atom_Member_Union_D(1)[of v s t1 t2]
by (auto dest!: types_fmD(6) assms(4) intro!: types_fmI(3,4))
next
case (4 s t1 t2)
with assms have "v ⊢ last b"
by (metis empty_iff empty_set last_in_set)
from assms "4"(2,3) show ?thesis
unfolding "4"(1)
using types_if_types_Member_and_subterms[where ?f="(⊓⇩s)", OF _ ‹v ⊢ last b› "4"(3),
THEN types_pset_atom_Member_Inter_D(2)]
by (force dest!: types_fmD(6) assms(4) intro!: types_fmI(3,4))
next
case (5 s t1 t2)
with assms have "v ⊢ last b"
by (metis empty_iff empty_set last_in_set)
from assms "5"(2,3) show ?thesis
unfolding "5"(1)
using types_if_types_Member_and_subterms[where ?f="(-⇩s)", OF _ ‹v ⊢ last b› "5"(3),
THEN types_pset_atom_Member_Diff_D(2)]
by (force dest!: types_fmD(6) assms(4) intro!: types_fmI(3,4))
qed
lemma types_term_if_on_vars_eq:
assumes "∀x ∈ vars t. v' x = v x"
shows "v' ⊢ t : l ⟷ v ⊢ t : l"
using assms
apply(induction t arbitrary: l)
apply(auto intro!: types_pset_term_intros' types_pset_term.intros(4-)
elim!: types_pset_term_cases)
done
lemma types_pset_atom_if_on_vars_eq:
fixes a :: "'a pset_atom"
assumes "∀x ∈ vars a. v' x = v x"
shows "v' ⊢ a ⟷ v ⊢ a"
using assms
by (auto simp: ball_Un types_pset_atom.simps dest!: types_term_if_on_vars_eq)
lemma types_pset_fm_if_on_vars_eq:
fixes φ :: "'a pset_fm"
assumes "∀x ∈ vars φ. v' x = v x"
shows "v' ⊢ φ ⟷ v ⊢ φ"
using assms types_pset_atom_if_on_vars_eq
unfolding types_pset_fm_def vars_fm_def by fastforce
lemma types_term_fun_upd:
assumes "x ∉ vars t"
shows "v(x := l) ⊢ t : l ⟷ v ⊢ t : l"
using assms types_term_if_on_vars_eq by (metis fun_upd_other)
lemma types_pset_atom_fun_upd:
fixes a :: "'a pset_atom"
assumes "x ∉ vars a"
shows "v(x := l) ⊢ a ⟷ v ⊢ a"
using assms types_pset_atom_if_on_vars_eq by (metis fun_upd_other)
lemma types_pset_fm_fun_upd:
fixes φ :: "'a pset_fm"
assumes "x ∉ vars φ"
shows "v(x := l) ⊢ φ ⟷ v ⊢ φ"
using assms types_pset_fm_if_on_vars_eq by (metis fun_upd_other)
lemma types_bexpands_wit:
fixes b :: "'a branch" and bs' :: "'a branch set"
assumes "bexpands_wit t1 t2 x bs' b" "b ≠ []"
assumes "⋀(φ :: 'a pset_fm). φ ∈ set b ⟹ v ⊢ φ"
obtains l where "∀φ ∈ set b. v(x := l) ⊢ φ"
"∀b' ∈ bs'. ∀φ ∈ set b'. v(x := l) ⊢ φ"
using assms(1)
proof(cases rule: bexpands_wit.cases)
case 1
from assms(3)[OF "1"(2)] obtain lt where lt: "v ⊢ t1 : lt" "v ⊢ t2 : lt"
by (auto dest!: types_fmD simp: types_pset_atom.simps)
with 1 assms(2,3) have "lt ≠ 0"
unfolding urelem_def using last_in_set by metis
with lt obtain ltp where ltp: "v ⊢ t1 : Suc ltp" "v ⊢ t2 : Suc ltp"
using not0_implies_Suc by blast
with assms(3) have "∀φ ∈ set b. v(x := ltp) ⊢ φ"
using types_pset_fm_fun_upd ‹x ∉ vars b› by (metis vars_fm_vars_branchI)
moreover from ‹x ∉ vars b› ‹AF (t1 =⇩s t2) ∈ set b› have not_in_vars: "x ∉ vars t1" "x ∉ vars t2"
using assms(2) by (auto simp: vars_fm_vars_branchI)
from this[THEN types_term_fun_upd] have "∀b' ∈ bs'. ∀φ ∈ set b'. v(x := ltp) ⊢ φ"
using ltp unfolding "1"(1)
apply(auto intro!: types_fmI types_pset_term_intros'(2) simp: types_pset_atom.simps)
apply (metis fun_upd_same fun_upd_upd types_pset_term.intros(2))+
done
ultimately show ?thesis
using that by blast
qed
lemma types_expandss:
fixes b b' :: "'a branch"
assumes "expandss b' b" "b ≠ []"
assumes "⋀φ. φ ∈ set b ⟹ v ⊢ φ"
obtains v' where "∀x ∈ vars b. v' x = v x" "∀φ ∈ set b'. v' ⊢ φ"
using assms
proof(induction b' b arbitrary: thesis rule: expandss.induct)
case (1 b)
then show ?case by blast
next
case (2 b3 b2 b1)
then obtain v' where v': "∀x ∈ vars b1. v' x = v x" "∀φ ∈ set b2. v' ⊢ φ"
by blast
with types_lexpands[OF ‹lexpands b3 b2›] have "∀φ ∈ set b3. v' ⊢ φ"
using expandss_not_Nil[OF ‹expandss b2 b1› ‹b1 ≠ []›] by blast
with v' "2.prems" show ?case
by force
next
case (3 bs b2 b3 b1)
then obtain v' where v': "∀x ∈ vars b1. v' x = v x" "∀φ ∈ set b2. v' ⊢ φ"
by blast
from ‹bexpands bs b2› show ?case
proof(cases rule: bexpands.cases)
case 1
from types_bexpands_nowit[OF this] v' ‹b3 ∈ bs› have "∀φ ∈ set b3. v' ⊢ φ"
by blast
with v' "3.prems" show ?thesis
by force
next
case (2 t1 t2 x)
from types_bexpands_wit[OF this] v' ‹b3 ∈ bs› obtain l
where "∀φ ∈ set b3. v'(x := l) ⊢ φ"
using expandss_not_Nil[OF ‹expandss b2 b1› ‹b1 ≠ []›] by metis
moreover from bexpands_witD(9)[OF 2] have "x ∉ vars b1"
using expandss_mono[OF ‹expandss b2 b1›] unfolding vars_branch_def by blast
then have "∀y ∈ vars b1. (v'(x := l)) y = v y"
using v'(1) by simp
moreover from ‹x ∉ vars b2› v'(2) have "∀φ ∈ set b2. v'(x := l) ⊢ φ"
by (meson types_pset_fm_fun_upd vars_fm_vars_branchI)
ultimately show ?thesis
using v' "3.prems"(1)[where ?v'="v'(x := l)"] by fastforce
qed
qed
lemma urelem_invar_if_wf_branch:
assumes "wf_branch b"
assumes "urelem (last b) x" "x ∈ subterms (last b)"
shows "∃v. ∀φ ∈ set b. urelem' v φ x"
proof -
from assms obtain v where v: "v ⊢ last b" "v ⊢ x : 0"
unfolding urelem_def by blast
moreover from assms have "expandss b [last b]"
by (metis expandss_last_eq last.simps list.distinct(1) wf_branch_def)
from types_expandss[OF this, simplified] v obtain v' where
"∀x ∈ vars (last b). v' x = v x" "∀φ ∈ set b. v' ⊢ φ"
by (metis list.set_intros(1) vars_fm_vars_branchI)
ultimately show ?thesis
unfolding urelem_def using assms
by (metis mem_vars_fm_if_mem_subterms_fm types_term_if_on_vars_eq)
qed
lemma not_types_term_0_if_types_term:
fixes s :: "'a pset_term"
assumes "f t1 t2 ∈ subterms s" "f ∈ {(⊓⇩s), (⊔⇩s), (-⇩s)}"
assumes "v ⊢ f t1 t2 : l"
shows "¬ v ⊢ t1 : 0" "¬ v ⊢ t2 : 0"
using assms
by (induction s arbitrary: l)
(auto elim: types_pset_term_cases dest: types_term_unique)
lemma types_term_subterms:
assumes "t ∈ subterms s"
assumes "v ⊢ s : ls"
obtains lt where "v ⊢ t : lt"
using assms
by (induction s arbitrary: ls) (auto elim: types_pset_term_cases dest: types_term_unique)
lemma types_atom_subterms:
fixes a :: "'a pset_atom"
assumes "t ∈ subterms a"
assumes "v ⊢ a"
obtains lt where "v ⊢ t : lt"
using assms
by (cases a) (fastforce elim: types_term_subterms simp: types_pset_atom.simps)+
lemma subterms_type_pset_fm_not_None:
fixes φ :: "'a pset_fm"
assumes "t ∈ subterms φ"
assumes "v ⊢ φ"
obtains lt where "v ⊢ t : lt"
using assms
by (induction φ) (auto elim: types_atom_subterms dest: types_fmD(1-5) dest!: types_fmD(6))
lemma not_urelem_comps_if_compound:
assumes "f t1 t2 ∈ subterms φ" "f ∈ {(⊓⇩s), (⊔⇩s), (-⇩s)}"
shows "¬ urelem φ t1" "¬ urelem φ t2"
proof -
from assms have "¬ v ⊢ t1 : 0" "¬ v ⊢ t2 : 0" if "v ⊢ φ" for v
using that not_types_term_0_if_types_term[OF _ _ subterms_type_pset_fm_not_None]
using subterms_refl by metis+
then show "¬ urelem φ t1" "¬ urelem φ t2"
unfolding urelem_def by blast+
qed
end
end