Theory SimplyTyped
theory SimplyTyped
imports PreSimplyTyped
begin
quotient_type 'a trm = "'a ptrm" / ptrm_alpha_equiv
proof(rule equivpI)
show "reflp ptrm_alpha_equiv" using ptrm_alpha_equiv_reflp.
show "symp ptrm_alpha_equiv" using ptrm_alpha_equiv_symp.
show "transp ptrm_alpha_equiv" using ptrm_alpha_equiv_transp.
qed
lift_definition Unit :: "'a trm" is PUnit.
lift_definition Var :: "'a ⇒ 'a trm" is PVar.
lift_definition App :: "'a trm ⇒ 'a trm ⇒ 'a trm" is PApp using ptrm_alpha_equiv.app.
lift_definition Fn :: "'a ⇒ type ⇒ 'a trm ⇒ 'a trm" is PFn using ptrm_alpha_equiv.fn1.
lift_definition Pair :: "'a trm ⇒ 'a trm ⇒ 'a trm" is PPair using ptrm_alpha_equiv.pair.
lift_definition Fst :: "'a trm ⇒ 'a trm" is PFst using ptrm_alpha_equiv.fst.
lift_definition Snd :: "'a trm ⇒ 'a trm" is PSnd using ptrm_alpha_equiv.snd.
lift_definition fvs :: "'a trm ⇒ 'a set" is ptrm_fvs using ptrm_alpha_equiv_fvs.
lift_definition prm :: "'a prm ⇒ 'a trm ⇒ 'a trm" (infixr "⋅" 150) is ptrm_apply_prm
using ptrm_alpha_equiv_prm.
lift_definition depth :: "'a trm ⇒ nat" is size using ptrm_size_alpha_equiv.
lemma depth_prm:
shows "depth (π ⋅ A) = depth A"
by(transfer, metis ptrm_size_prm)
lemma depth_app:
shows "depth A < depth (App A B)" "depth B < depth (App A B)"
by(transfer, auto)+
lemma depth_fn:
shows "depth A < depth (Fn x T A)"
by(transfer, auto)
lemma depth_pair:
shows "depth A < depth (Pair A B)" "depth B < depth (Pair A B)"
by(transfer, auto)+
lemma depth_fst:
shows "depth P < depth (Fst P)"
by(transfer, auto)
lemma depth_snd:
shows "depth P < depth (Snd P)"
by(transfer, auto)
lemma unit_not_var:
shows "Unit ≠ Var x"
proof(transfer)
fix x :: 'a
show "¬ PUnit ≈ PVar x"
proof(rule classical)
assume "¬¬ PUnit ≈ PVar x"
hence False using unitE by fastforce
thus ?thesis by blast
qed
qed
lemma unit_not_app:
shows "Unit ≠ App A B"
proof(transfer)
fix A B :: "'a ptrm"
show "¬ PUnit ≈ PApp A B"
proof(rule classical)
assume "¬¬ PUnit ≈ PApp A B"
hence False using unitE by fastforce
thus ?thesis by blast
qed
qed
lemma unit_not_fn:
shows "Unit ≠ Fn x T A"
proof(transfer)
fix x :: 'a and T A
show "¬ PUnit ≈ PFn x T A"
proof(rule classical)
assume "¬¬ PUnit ≈ PFn x T A"
hence False using unitE by fastforce
thus ?thesis by blast
qed
qed
lemma unit_not_pair:
shows "Unit ≠ Pair A B"
proof(transfer)
fix A B :: "'a ptrm"
show "¬ PUnit ≈ PPair A B"
proof(rule classical)
assume "¬¬ PUnit ≈ PPair A B"
hence False using unitE by fastforce
thus ?thesis by blast
qed
qed
lemma unit_not_fst:
shows "Unit ≠ Fst P"
proof(transfer)
fix P :: "'a ptrm"
show "¬ PUnit ≈ PFst P"
proof(rule classical)
assume "¬¬ PUnit ≈ PFst P"
hence False using unitE by fastforce
thus ?thesis by blast
qed
qed
lemma unit_not_snd:
shows "Unit ≠ Snd P"
proof(transfer)
fix P :: "'a ptrm"
show "¬ PUnit ≈ PSnd P"
proof(rule classical)
assume "¬¬ PUnit ≈ PSnd P"
hence False using unitE by fastforce
thus ?thesis by blast
qed
qed
lemma var_not_app:
shows "Var x ≠ App A B"
proof(transfer)
fix x :: 'a and A B
show "¬PVar x ≈ PApp A B"
proof(rule classical)
assume "¬¬PVar x ≈ PApp A B"
hence False using varE by fastforce
thus ?thesis by blast
qed
qed
lemma var_not_fn:
shows "Var x ≠ Fn y T A"
proof(transfer)
fix x y :: 'a and T A
show "¬PVar x ≈ PFn y T A"
proof(rule classical)
assume "¬¬PVar x ≈ PFn y T A"
hence False using varE by fastforce
thus ?thesis by blast
qed
qed
lemma var_not_pair:
shows "Var x ≠ Pair A B"
proof(transfer)
fix x :: 'a and A B
show "¬PVar x ≈ PPair A B"
proof(rule classical)
assume "¬¬PVar x ≈ PPair A B"
hence False using varE by fastforce
thus ?thesis by blast
qed
qed
lemma var_not_fst:
shows "Var x ≠ Fst P"
proof(transfer)
fix x :: 'a and P
show "¬PVar x ≈ PFst P"
proof(rule classical)
assume "¬¬PVar x ≈ PFst P"
hence False using varE by fastforce
thus ?thesis by blast
qed
qed
lemma var_not_snd:
shows "Var x ≠ Snd P"
proof(transfer)
fix x :: 'a and P
show "¬PVar x ≈ PSnd P"
proof(rule classical)
assume "¬¬PVar x ≈ PSnd P"
hence False using varE by fastforce
thus ?thesis by blast
qed
qed
lemma app_not_fn:
shows "App A B ≠ Fn y T X"
proof(transfer)
fix y :: 'a and A B T X
show "¬PApp A B ≈ PFn y T X"
proof(rule classical)
assume "¬¬PApp A B ≈ PFn y T X"
hence False using appE by auto
thus ?thesis by blast
qed
qed
lemma app_not_pair:
shows "App A B ≠ Pair C D"
proof(transfer)
fix A B C D :: "'a ptrm"
show "¬PApp A B ≈ PPair C D"
proof(rule classical)
assume "¬¬PApp A B ≈ PPair C D"
hence False using appE by auto
thus ?thesis by blast
qed
qed
lemma app_not_fst:
shows "App A B ≠ Fst P"
proof(transfer)
fix A B P :: "'a ptrm"
show "¬PApp A B ≈ PFst P"
proof(rule classical)
assume "¬¬PApp A B ≈ PFst P"
hence False using appE by auto
thus ?thesis by blast
qed
qed
lemma app_not_snd:
shows "App A B ≠ Snd P"
proof(transfer)
fix A B P :: "'a ptrm"
show "¬PApp A B ≈ PSnd P"
proof(rule classical)
assume "¬¬PApp A B ≈ PSnd P"
hence False using appE by auto
thus ?thesis by blast
qed
qed
lemma fn_not_pair:
shows "Fn x T A ≠ Pair C D"
proof(transfer)
fix x :: 'a and T A C D
show "¬PFn x T A ≈ PPair C D"
proof(rule classical)
assume "¬¬PFn x T A ≈ PPair C D"
hence False using fnE by fastforce
thus ?thesis by blast
qed
qed
lemma fn_not_fst:
shows "Fn x T A ≠ Fst P"
proof(transfer)
fix x :: 'a and T A P
show "¬PFn x T A ≈ PFst P"
proof(rule classical)
assume "¬¬PFn x T A ≈ PFst P"
hence False using fnE by fastforce
thus ?thesis by blast
qed
qed
lemma fn_not_snd:
shows "Fn x T A ≠ Snd P"
proof(transfer)
fix x :: 'a and T A P
show "¬PFn x T A ≈ PSnd P"
proof(rule classical)
assume "¬¬PFn x T A ≈ PSnd P"
hence False using fnE by fastforce
thus ?thesis by blast
qed
qed
lemma pair_not_fst:
shows "Pair A B ≠ Fst P"
proof(transfer)
fix A B P :: "'a ptrm"
show "¬PPair A B ≈ PFst P"
proof(rule classical)
assume "¬¬PPair A B ≈ PFst P"
hence False using pairE by auto
thus ?thesis by blast
qed
qed
lemma pair_not_snd:
shows "Pair A B ≠ Snd P"
proof(transfer)
fix A B P :: "'a ptrm"
show "¬PPair A B ≈ PSnd P"
proof(rule classical)
assume "¬¬PPair A B ≈ PSnd P"
hence False using pairE by auto
thus ?thesis by blast
qed
qed
lemma fst_not_snd:
shows "Fst P ≠ Snd Q"
proof(transfer)
fix P Q :: "'a ptrm"
show "¬PFst P ≈ PSnd Q"
proof(rule classical)
assume "¬¬PFst P ≈ PSnd Q"
hence False using fstE by auto
thus ?thesis by blast
qed
qed
lemma trm_simp:
shows
"Var x = Var y ⟹ x = y"
"App A B = App C D ⟹ A = C"
"App A B = App C D ⟹ B = D"
"Fn x T A = Fn y S B ⟹
(x = y ∧ T = S ∧ A = B) ∨ (x ≠ y ∧ T = S ∧ x ∉ fvs B ∧ A = [x ↔ y] ⋅ B)"
"Pair A B = Pair C D ⟹ A = C"
"Pair A B = Pair C D ⟹ B = D"
"Fst P = Fst Q ⟹ P = Q"
"Snd P = Snd Q ⟹ P = Q"
proof -
show "Var x = Var y ⟹ x = y" by (transfer, insert ptrm.inject varE, fastforce)
show "App A B = App C D ⟹ A = C" by (transfer, insert ptrm.inject appE, auto)
show "App A B = App C D ⟹ B = D" by (transfer, insert ptrm.inject appE, auto)
show "Pair A B = Pair C D ⟹ A = C" by (transfer, insert ptrm.inject pairE, auto)
show "Pair A B = Pair C D ⟹ B = D" by (transfer, insert ptrm.inject pairE, auto)
show "Fst P = Fst Q ⟹ P = Q" by (transfer, insert ptrm.inject fstE, auto)
show "Snd P = Snd Q ⟹ P = Q" by (transfer, insert ptrm.inject sndE, auto)
show "Fn x T A = Fn y S B ⟹
(x = y ∧ T = S ∧ A = B) ∨ (x ≠ y ∧ T = S ∧ x ∉ fvs B ∧ A = [x ↔ y] ⋅ B)"
proof(transfer')
fix x y :: 'a and T S :: type and A B :: "'a ptrm"
assume *: "PFn x T A ≈ PFn y S B"
thus "x = y ∧ T = S ∧ A ≈ B ∨ x ≠ y ∧ T = S ∧ x ∉ ptrm_fvs B ∧ A ≈ [x ↔ y] ∙ B"
proof(induction rule: fnE[where x=x and T=T and A=A and Y="PFn y S B"], metis *)
case (2 C)
thus ?case by simp
next
case (3 z C)
thus ?case by simp
next
qed
qed
qed
lemma fn_eq:
assumes "x ≠ y" "x ∉ fvs B" "A = [x ↔ y] ⋅ B"
shows "Fn x T A = Fn y T B"
using assms by(transfer', metis ptrm_alpha_equiv.fn2)
lemma trm_prm_simp:
shows
"π ⋅ Unit = Unit"
"π ⋅ Var x = Var (π $ x)"
"π ⋅ App A B = App (π ⋅ A) (π ⋅ B)"
"π ⋅ Fn x T A = Fn (π $ x) T (π ⋅ A)"
"π ⋅ Pair A B = Pair (π ⋅ A) (π ⋅ B)"
"π ⋅ Fst P = Fst (π ⋅ P)"
"π ⋅ Snd P = Snd (π ⋅ P)"
apply (transfer, auto simp add: ptrm_alpha_equiv_reflexive)
apply (transfer', auto simp add: ptrm_alpha_equiv_reflexive)
apply ((transfer, auto simp add: ptrm_alpha_equiv_reflexive)+)
done
lemma trm_prm_apply_compose:
shows "π ⋅ σ ⋅ A = (π ⋄ σ) ⋅ A"
by(transfer', metis ptrm_prm_apply_compose ptrm_alpha_equiv_reflexive)
lemma fvs_finite:
shows "finite (fvs M)"
by(transfer, metis ptrm_fvs_finite)
lemma fvs_simp:
shows
"fvs Unit = {}" and
"fvs (Var x) = {x}"
"fvs (App A B) = fvs A ∪ fvs B"
"fvs (Fn x T A) = fvs A - {x}"
"fvs (Pair A B) = fvs A ∪ fvs B"
"fvs (Fst P) = fvs P"
"fvs (Snd P) = fvs P"
by((transfer, simp)+)
lemma var_prm_action:
shows "[a ↔ b] ⋅ Var a = Var b"
by(transfer', simp add: prm_unit_action ptrm_alpha_equiv.intros)
lemma var_prm_inaction:
assumes "a ≠ x" "b ≠ x"
shows "[a ↔ b] ⋅ Var x = Var x"
using assms by(transfer', simp add: prm_unit_inaction ptrm_alpha_equiv.intros)
lemma trm_prm_apply_id:
shows "ε ⋅ M = M"
by(transfer', auto simp add: ptrm_prm_apply_id)
lemma trm_prm_unit_inaction:
assumes "a ∉ fvs X" "b ∉ fvs X"
shows "[a ↔ b] ⋅ X = X"
using assms by(transfer', metis ptrm_prm_unit_inaction)
lemma trm_prm_agreement_equiv:
assumes "⋀a. a ∈ ds π σ ⟹ a ∉ fvs M"
shows "π ⋅ M = σ ⋅ M"
using assms by(transfer, metis ptrm_prm_agreement_equiv)
lemma trm_induct:
fixes P :: "'a trm ⇒ bool"
assumes
"P Unit"
"⋀x. P (Var x)"
"⋀A B. ⟦P A; P B⟧ ⟹ P (App A B)"
"⋀x T A. P A ⟹ P (Fn x T A)"
"⋀A B. ⟦P A; P B⟧ ⟹ P (Pair A B)"
"⋀A. P A ⟹ P (Fst A)"
"⋀A. P A ⟹ P (Snd A)"
shows "P M"
proof -
have "⋀X. P (abs_trm X)"
proof(rule ptrm.induct)
show "P (abs_trm PUnit)"
using assms(1) Unit.abs_eq by metis
show "P (abs_trm (PVar x))" for x
using assms(2) Var.abs_eq by metis
show "⟦P (abs_trm A); P (abs_trm B)⟧ ⟹ P (abs_trm (PApp A B))" for A B
using assms(3) App.abs_eq by metis
show "P (abs_trm A) ⟹ P (abs_trm (PFn x T A))" for x T A
using assms(4) Fn.abs_eq by metis
show "⟦P (abs_trm A); P (abs_trm B)⟧ ⟹ P (abs_trm (PPair A B))" for A B
using assms(5) Pair.abs_eq by metis
show "P (abs_trm A) ⟹ P (abs_trm (PFst A))" for A
using assms(6) Fst.abs_eq by metis
show "P (abs_trm A) ⟹ P (abs_trm (PSnd A))" for A
using assms(7) Snd.abs_eq by metis
qed
thus ?thesis using trm.abs_induct by auto
qed
lemma trm_cases:
assumes
"M = Unit ⟹ P M"
"⋀x. M = Var x ⟹ P M"
"⋀A B. M = App A B ⟹ P M"
"⋀x T A. M = Fn x T A ⟹ P M"
"⋀A B. M = Pair A B ⟹ P M"
"⋀A. M = Fst A ⟹ P M"
"⋀A. M = Snd A ⟹ P M"
shows "P M"
using assms by(induction rule: trm_induct, auto)
lemma trm_depth_induct:
assumes
"P Unit"
"⋀x. P (Var x)"
"⋀A B. ⟦⋀K. depth K < depth (App A B) ⟹ P K⟧ ⟹ P (App A B)"
"⋀M x T A. (⋀K. depth K < depth (Fn x T A) ⟹ P K) ⟹ P (Fn x T A)"
"⋀A B. ⟦⋀K. depth K < depth (Pair A B) ⟹ P K⟧ ⟹ P (Pair A B)"
"⋀A. ⟦⋀K. depth K < depth (Fst A) ⟹ P K⟧ ⟹ P (Fst A)"
"⋀A. ⟦⋀K. depth K < depth (Snd A) ⟹ P K⟧ ⟹ P (Snd A)"
shows "P M"
proof(induction "depth M" arbitrary: M rule: less_induct)
fix M :: "'a trm"
assume IH: "depth K < depth M ⟹ P K" for K
hence
" M = Unit ⟹ P M"
"⋀x. M = Var x ⟹ P M"
"⋀A B. M = App A B ⟹ P M"
"⋀x T A. M = Fn x T A ⟹ P M"
"⋀A B. M = Pair A B ⟹ P M"
"⋀A. M = Fst A ⟹ P M"
"⋀A. M = Snd A ⟹ P M"
using assms by blast+
thus "P M" using trm_cases[where M=M] by blast
qed
context fresh begin
lemma fresh_fn:
fixes x :: 'a and S :: "'a set"
assumes "finite S"
shows "∃y B. y ∉ S ∧ B = [y ↔ x] ⋅ A ∧ (Fn x T A = Fn y T B)"
proof -
have *: "finite ({x} ∪ fvs A ∪ S)" using fvs_finite assms by auto
obtain y where "y = fresh_in ({x} ∪ fvs A ∪ S)" by auto
hence "y ∉ ({x} ∪ fvs A ∪ S)" using fresh_axioms * unfolding class.fresh_def by metis
hence "y ≠ x" "y ∉ fvs A" "y ∉ S" by auto
obtain B where B: "B = [y ↔ x] ⋅ A" by auto
hence "Fn x T A = Fn y T B" using fn_eq ‹y ≠ x› ‹y ∉ fvs A› by metis
thus ?thesis using ‹y ≠ x› ‹y ∉ S› B by metis
qed
lemma trm_strong_induct:
fixes P :: "'a set ⇒ 'a trm ⇒ bool"
assumes
"P S Unit"
"⋀x. P S (Var x)"
"⋀A B. ⟦P S A; P S B⟧ ⟹ P S (App A B)"
"⋀x T. x ∉ S ⟹ (⋀A. P S A ⟹ P S (Fn x T A))"
"⋀A B. ⟦P S A; P S B⟧ ⟹ P S (Pair A B)"
"⋀A. P S A ⟹ P S (Fst A)"
"⋀A. P S A ⟹ P S (Snd A)"
"finite S"
shows "P S M"
proof -
have "⋀π. P S (π ⋅ M)"
proof(induction M rule: trm_induct)
case 1
thus ?case using assms(1) trm_prm_simp(1) by metis
next
case (2 x)
thus ?case using assms(2) trm_prm_simp(2) by metis
next
case (3 A B)
thus ?case using assms(3) trm_prm_simp(3) by metis
next
case (4 x T A)
have "finite S" "finite (fvs (π ⋅ A))" "finite {π $ x}"
using ‹finite S› fvs_finite by auto
hence "finite (S ∪ fvs (π ⋅ A) ∪ {π $ x})" by auto
obtain y where "y = fresh_in (S ∪ fvs (π ⋅ A) ∪ {π $ x})" by auto
hence "y ∉ S ∪ fvs (π ⋅ A) ∪ {π $ x}" using fresh_axioms unfolding class.fresh_def
using ‹finite (S ∪ fvs (π ⋅ A) ∪ {π $ x})› by metis
hence "y ≠ π $ x" "y ∉ fvs (π ⋅ A)" "y ∉ S" by auto
hence *: "⋀A. P S A ⟹ P S (Fn y T A)" using assms(4) by metis
have "P S (([y ↔ π $ x] ⋄ π) ⋅ A)" using 4 by metis
hence "P S (Fn y T (([y ↔ π $ x] ⋄ π) ⋅ A))" using * by metis
moreover have "(Fn y T (([y ↔ π $ x] ⋄ π) ⋅ A)) = Fn (π $ x) T (π ⋅ A)"
using trm_prm_apply_compose fn_eq ‹y ≠ π $ x› ‹y ∉ fvs (π ⋅ A)› by metis
ultimately show ?case using trm_prm_simp(4) by metis
next
case (5 A B)
thus ?case using assms(5) trm_prm_simp(5) by metis
next
case (6 A)
thus ?case using assms(6) trm_prm_simp(6) by metis
next
case (7 A)
thus ?case using assms(7) trm_prm_simp(7) by metis
next
qed
hence "P S (ε ⋅ M)" by metis
thus "P S M" using trm_prm_apply_id by metis
qed
lemma trm_strong_cases:
fixes P :: "'a set ⇒ 'a trm ⇒ bool"
assumes
" M = Unit ⟹ P S M"
"⋀x. M = Var x ⟹ P S M"
"⋀A B. M = App A B ⟹ P S M"
"⋀x T A. M = Fn x T A ⟹ x ∉ S ⟹ P S M"
"⋀A B. M = Pair A B ⟹ P S M"
"⋀A. M = Fst A ⟹ P S M"
"⋀A. M = Snd A ⟹ P S M"
"finite S"
shows "P S M"
using assms by(induction S M rule: trm_strong_induct, metis+)
lemma trm_strong_depth_induct:
fixes P :: "'a set ⇒ 'a trm ⇒ bool"
assumes
"P S Unit"
"⋀x. P S (Var x)"
"⋀A B. ⟦⋀K. depth K < depth (App A B) ⟹ P S K⟧ ⟹ P S (App A B)"
"⋀x T. x ∉ S ⟹ (⋀A. (⋀K. depth K < depth (Fn x T A) ⟹ P S K) ⟹ P S (Fn x T A))"
"⋀A B. ⟦⋀K. depth K < depth (Pair A B) ⟹ P S K⟧ ⟹ P S (Pair A B)"
"⋀A. ⟦⋀K. depth K < depth (Fst A) ⟹ P S K⟧ ⟹ P S (Fst A)"
"⋀A. ⟦⋀K. depth K < depth (Snd A) ⟹ P S K⟧ ⟹ P S (Snd A)"
"finite S"
shows "P S M"
proof(induction "depth M" arbitrary: M rule: less_induct)
fix M :: "'a trm"
assume IH: "depth K < depth M ⟹ P S K" for K
hence
" M = Unit ⟹ P S M"
"⋀x. M = Var x ⟹ P S M"
"⋀A B. M = App A B ⟹ P S M"
"⋀x T A. M = Fn x T A ⟹ x ∉ S ⟹ P S M"
"⋀A B. M = Pair A B ⟹ P S M"
"⋀A. M = Fst A ⟹ P S M"
"⋀A. M = Snd A ⟹ P S M"
"finite S"
using assms IH by metis+
thus "P S M" using trm_strong_cases[where M=M] by blast
qed
lemma trm_prm_fvs:
shows "fvs (π ⋅ M) = π {$} fvs M"
by(transfer, metis ptrm_prm_fvs)
inductive typing :: "'a typing_ctx ⇒ 'a trm ⇒ type ⇒ bool" ("_ ⊢ _ : _") where
tunit: "Γ ⊢ Unit : TUnit"
| tvar: "Γ x = Some τ ⟹ Γ ⊢ Var x : τ"
| tapp: "⟦Γ ⊢ f : (TArr τ σ); Γ ⊢ x : τ⟧ ⟹ Γ ⊢ App f x : σ"
| tfn: "Γ(x ↦ τ) ⊢ A : σ ⟹ Γ ⊢ Fn x τ A : (TArr τ σ)"
| tpair: "⟦Γ ⊢ A : τ; Γ ⊢ B : σ⟧ ⟹ Γ ⊢ Pair A B : (TPair τ σ)"
| tfst: "Γ ⊢ P : (TPair τ σ) ⟹ Γ ⊢ Fst P : τ"
| tsnd: "Γ ⊢ P : (TPair τ σ) ⟹ Γ ⊢ Snd P : σ"
lemma typing_prm:
assumes "Γ ⊢ M : τ" "⋀y. y ∈ fvs M ⟹ Γ y = Δ (π $ y)"
shows "Δ ⊢ π ⋅ M : τ"
using assms proof(induction arbitrary: Δ rule: typing.induct)
case (tunit Γ)
thus ?case using typing.tunit trm_prm_simp(1) by metis
next
case (tvar Γ x τ)
thus ?case using typing.tvar trm_prm_simp(2) fvs_simp(2) singletonI by metis
next
case (tapp Γ A τ σ B)
thus ?case using typing.tapp trm_prm_simp(3) fvs_simp(3) UnCI by metis
next
case (tfn Γ x τ A σ)
have "y ∈ fvs A ⟹ (Γ(x ↦ τ)) y = (Δ(π $ x ↦ τ)) (π $ y)" for y
proof(cases "y = x")
case True
thus ?thesis using fun_upd_apply by simp
next
case False
assume "y ∈ fvs A"
hence "y ∈ fvs (Fn x τ A)" using fvs_simp(4) ‹y ≠ x› DiffI singletonD by fastforce
hence "Γ y = Δ (π $ y)" using tfn.prems by metis
thus ?thesis by (simp add: prm_apply_unequal)
next
qed
hence "Δ(π $ x ↦ τ) ⊢ π ⋅ A : σ" using tfn.IH by metis
thus ?case using trm_prm_simp(4) typing.tfn by metis
next
case (tpair Γ A B)
thus ?case using typing.tpair trm_prm_simp(5) fvs_simp(5) UnCI by metis
next
case (tfst Γ P τ σ)
thus ?case using typing.tfst trm_prm_simp(6) fvs_simp(6) by metis
next
case (tsnd Γ P τ σ)
thus ?case using typing.tsnd trm_prm_simp(7) fvs_simp(7) by metis
next
qed
lemma typing_swp:
assumes "Γ(a ↦ σ) ⊢ M : τ" "b ∉ fvs M"
shows "Γ(b ↦ σ) ⊢ [a ↔ b] ⋅ M : τ"
proof -
have "y ∈ fvs M ⟹ (Γ(a ↦ σ)) y = (Γ(b ↦ σ)) ([a ↔ b] $ y)" for y
proof -
assume "y ∈ fvs M"
hence "y ≠ b" using assms(2) by auto
consider "y = a" | "y ≠ a" by auto
thus "(Γ(a ↦ σ)) y = (Γ(b ↦ σ)) ([a ↔ b] $ y)"
by(cases, simp add: prm_unit_action, simp add: prm_unit_inaction ‹y ≠ b›)
qed
thus ?thesis using typing_prm assms(1) by metis
qed
lemma typing_unitE:
assumes "Γ ⊢ Unit : τ"
shows "τ = TUnit"
using assms
apply cases
apply blast
apply (auto simp add: unit_not_var unit_not_app unit_not_fn unit_not_pair unit_not_fst unit_not_snd)
done
lemma typing_varE:
assumes "Γ ⊢ Var x : τ"
shows "Γ x = Some τ"
using assms
apply cases
prefer 2
apply (metis trm_simp(1))
apply (metis unit_not_var)
apply (auto simp add: var_not_app var_not_fn var_not_pair var_not_fst var_not_snd)
done
lemma typing_appE:
assumes "Γ ⊢ App A B : σ"
shows "∃τ. (Γ ⊢ A : (TArr τ σ)) ∧ (Γ ⊢ B : τ)"
using assms
apply cases
prefer 3
apply (metis trm_simp(2, 3))
apply (metis unit_not_app)
apply (metis var_not_app)
apply (auto simp add: app_not_fn app_not_pair app_not_fst app_not_snd)
done
lemma typing_fnE:
assumes "Γ ⊢ Fn x T A : θ"
shows "∃σ. θ = (TArr T σ) ∧ (Γ(x ↦ T) ⊢ A : σ)"
using assms proof(cases)
case (tfn y S B σ)
from this consider
"x = y ∧ T = S ∧ A = B" | "x ≠ y ∧ T = S ∧ x ∉ fvs B ∧ A = [x ↔ y] ⋅ B"
using trm_simp(4) by metis
thus ?thesis proof(cases)
case 1
thus ?thesis using tfn by metis
next
case 2
thus ?thesis using tfn typing_swp prm_unit_commutes by metis
next
qed
next
qed (
metis unit_not_fn,
metis var_not_fn,
metis app_not_fn,
metis fn_not_pair,
metis fn_not_fst,
metis fn_not_snd
)
lemma typing_pairE:
assumes "Γ ⊢ Pair A B : θ"
shows "∃τ σ. θ = (TPair τ σ) ∧ (Γ ⊢ A : τ) ∧ (Γ ⊢ B : σ)"
using assms proof(cases)
case (tpair A τ B σ)
thus ?thesis using trm_simp(5) trm_simp(6) by blast
next
qed (
metis unit_not_pair,
metis var_not_pair,
metis app_not_pair,
metis fn_not_pair,
metis pair_not_fst,
metis pair_not_snd
)
lemma typing_fstE:
assumes "Γ ⊢ Fst P : τ"
shows "∃σ. (Γ ⊢ P : (TPair τ σ))"
using assms proof(cases)
case (tfst P σ)
thus ?thesis using trm_simp(7) by blast
next
qed (
metis unit_not_fst,
metis var_not_fst,
metis app_not_fst,
metis fn_not_fst,
metis pair_not_fst,
metis fst_not_snd
)
lemma typing_sndE:
assumes "Γ ⊢ Snd P : σ"
shows "∃τ. (Γ ⊢ P : (TPair τ σ))"
using assms proof(cases)
case (tsnd P σ)
thus ?thesis using trm_simp(8) by blast
next
qed (
metis unit_not_snd,
metis var_not_snd,
metis app_not_snd,
metis fn_not_snd,
metis pair_not_snd,
metis fst_not_snd
)
theorem typing_weaken:
assumes "Γ ⊢ M : τ" "y ∉ fvs M"
shows "Γ(y ↦ σ) ⊢ M : τ"
using assms proof(induction rule: typing.induct)
case (tunit Γ)
thus ?case using typing.tunit by metis
next
case (tvar Γ x τ)
hence "y ≠ x" using fvs_simp(2) singletonI by force
hence "(Γ(y ↦ σ)) x = Some τ" using tvar.hyps fun_upd_apply by simp
thus ?case using typing.tvar by metis
next
case (tapp Γ f τ τ' x)
from ‹y ∉ fvs (App f x)› have "y ∉ fvs f" "y ∉ fvs x" using fvs_simp(3) Un_iff by force+
hence "Γ(y ↦ σ) ⊢ f : (TArr τ τ')" "Γ(y ↦ σ) ⊢ x : τ" using tapp.IH by metis+
thus ?case using typing.tapp by metis
next
case (tfn Γ x τ A τ')
from ‹y ∉ fvs (Fn x τ A)› consider "y = x" | "y ≠ x ∧ y ∉ fvs A"
using fvs_simp(4) DiffI empty_iff insert_iff by fastforce
thus ?case proof(cases)
case 1
hence "(Γ(y ↦ σ, x ↦ τ)) ⊢ A : τ'" using tfn.hyps fun_upd_upd by simp
thus ?thesis using typing.tfn by metis
next
case 2
hence "y ≠ x" "y ∉ fvs A" by auto
hence "Γ(x ↦ τ, y ↦ σ) ⊢ A : τ'" using tfn.IH by metis
hence "Γ(y ↦ σ, x ↦ τ) ⊢ A : τ'" using ‹y ≠ x› fun_upd_twist by metis
thus ?thesis using typing.tfn by metis
next
qed
next
case (tpair Γ A τ B σ)
thus ?case using typing.tpair fvs_simp(5) UnCI by metis
next
case (tfst Γ P τ σ)
thus ?case using typing.tfst fvs_simp(6) by metis
next
case (tsnd Γ P τ σ)
thus ?case using typing.tsnd fvs_simp(7) by metis
next
qed
lift_definition infer :: "'a typing_ctx ⇒ 'a trm ⇒ type option" is ptrm_infer_type
using ptrm_infer_type_alpha_equiv.
export_code infer fresh_nat_inst.fresh_in_nat in Haskell
lemma infer_simp:
shows
"infer Γ Unit = Some TUnit"
"infer Γ (Var x) = Γ x"
"infer Γ (App A B) = (case (infer Γ A, infer Γ B) of
(Some (TArr τ σ), Some τ') ⇒ (if τ = τ' then Some σ else None)
| _ ⇒ None
)"
"infer Γ (Fn x τ A) = (case infer (Γ(x ↦ τ)) A of
Some σ ⇒ Some (TArr τ σ)
| None ⇒ None
)"
"infer Γ (Pair A B) = (case (infer Γ A, infer Γ B) of
(Some τ, Some σ) ⇒ Some (TPair τ σ)
| _ ⇒ None
)"
"infer Γ (Fst P) = (case infer Γ P of
(Some (TPair τ σ)) ⇒ Some τ
| _ ⇒ None
)"
"infer Γ (Snd P) = (case infer Γ P of
(Some (TPair τ σ)) ⇒ Some σ
| _ ⇒ None
)"
by((transfer, simp)+)
lemma infer_unitE:
assumes "infer Γ Unit = Some τ"
shows "τ = TUnit"
using assms by(transfer, simp)
lemma infer_varE:
assumes "infer Γ (Var x) = Some τ"
shows "Γ x = Some τ"
using assms by(transfer, simp)
lemma infer_appE:
assumes "infer Γ (App A B) = Some τ"
shows "∃σ. infer Γ A = Some (TArr σ τ) ∧ infer Γ B = Some σ"
using assms proof(transfer)
fix Γ :: "'a typing_ctx" and A B τ
assume H: "ptrm_infer_type Γ (PApp A B) = Some τ"
have "ptrm_infer_type Γ A ≠ None"
proof(rule classical, auto)
assume "ptrm_infer_type Γ A = None"
hence "ptrm_infer_type Γ (PApp A B) = None" by auto
thus False using H by auto
qed
from this obtain T where *: "ptrm_infer_type Γ A = Some T" by auto
have "T ≠ TVar x" for x
proof(rule classical, auto)
fix x
assume "T = TVar x"
hence "ptrm_infer_type Γ A = Some (TVar x)" using * by metis
hence "ptrm_infer_type Γ (PApp A B) = None" by simp
thus False using H by auto
qed
moreover have "T ≠ TUnit"
proof(rule classical, auto)
fix x
assume "T = TUnit"
hence "ptrm_infer_type Γ A = Some TUnit" using * by metis
hence "ptrm_infer_type Γ (PApp A B) = None" by simp
thus False using H by auto
qed
moreover have "T ≠ TPair τ σ" for τ σ
proof(rule classical, auto)
fix τ σ
assume "T = TPair τ σ"
hence "ptrm_infer_type Γ A = Some (TPair τ σ)" using * by metis
hence "ptrm_infer_type Γ (PApp A B) = None" by simp
thus False using H by auto
qed
ultimately obtain σ τ' where "T = TArr σ τ'" by(cases T, blast, auto)
hence *: "ptrm_infer_type Γ A = Some (TArr σ τ')" using * by metis
have "ptrm_infer_type Γ B ≠ None"
proof(rule classical, auto)
assume "ptrm_infer_type Γ B = None"
hence "ptrm_infer_type Γ (PApp A B) = None" using * by auto
thus False using H by auto
qed
from this obtain σ' where **: "ptrm_infer_type Γ B = Some σ'" by auto
have "σ = σ'"
proof(rule classical)
assume "σ ≠ σ'"
hence "ptrm_infer_type Γ (PApp A B) = None" using * ** by simp
hence False using H by auto
thus "σ = σ'" by blast
qed
hence **: "ptrm_infer_type Γ B = Some σ" using ** by auto
have "ptrm_infer_type Γ (PApp A B) = Some τ'" using * ** by auto
hence "τ = τ'" using H by auto
hence *: "ptrm_infer_type Γ A = Some (TArr σ τ)" using * by auto
show "∃σ. ptrm_infer_type Γ A = Some (TArr σ τ) ∧ ptrm_infer_type Γ B = Some σ"
using * ** by auto
qed
lemma infer_fnE:
assumes "infer Γ (Fn x T A) = Some τ"
shows "∃σ. τ = TArr T σ ∧ infer (Γ(x ↦ T)) A = Some σ"
using assms proof(transfer)
fix x :: 'a and Γ T A τ
assume H: "ptrm_infer_type Γ (PFn x T A) = Some τ"
have "ptrm_infer_type (Γ(x ↦ T)) A ≠ None"
proof(rule classical, auto)
assume "ptrm_infer_type (Γ(x ↦ T)) A = None"
hence "ptrm_infer_type Γ (PFn x T A) = None" by auto
thus False using H by auto
qed
from this obtain σ where *: "ptrm_infer_type (Γ(x ↦ T)) A = Some σ" by auto
have "ptrm_infer_type Γ (PFn x T A) = Some (TArr T σ)" using * by auto
hence "τ = TArr T σ" using H by auto
thus "∃σ. τ = TArr T σ ∧ ptrm_infer_type (Γ(x ↦ T)) A = Some σ"
using * by auto
qed
lemma infer_pairE:
assumes "infer Γ (Pair A B) = Some τ"
shows "∃T S. τ = TPair T S ∧ infer Γ A = Some T ∧ infer Γ B = Some S"
using assms proof(transfer)
fix A B :: "'a ptrm" and Γ τ
assume H: "ptrm_infer_type Γ (PPair A B) = Some τ"
have "ptrm_infer_type Γ A ≠ None"
proof(rule classical, auto)
assume "ptrm_infer_type Γ A = None"
hence "ptrm_infer_type Γ (PPair A B) = None" by auto
thus False using H by auto
qed
moreover have "ptrm_infer_type Γ B ≠ None"
proof(rule classical, auto)
assume "ptrm_infer_type Γ B = None"
hence "ptrm_infer_type Γ (PPair A B) = None" by (simp add: option.case_eq_if)
thus False using H by auto
qed
ultimately obtain T S
where "τ = TPair T S" "ptrm_infer_type Γ A = Some T" "ptrm_infer_type Γ B = Some S"
using H by auto
thus "∃T S. τ = TPair T S ∧ ptrm_infer_type Γ A = Some T ∧ ptrm_infer_type Γ B = Some S" by auto
qed
lemma infer_fstE:
assumes "infer Γ (Fst P) = Some τ"
shows "∃T S. infer Γ P = Some (TPair T S) ∧ τ = T"
using assms proof(transfer)
fix P :: "'a ptrm" and Γ τ
assume H: "ptrm_infer_type Γ (PFst P) = Some τ"
have "ptrm_infer_type Γ P ≠ None"
proof(rule classical, auto)
assume "ptrm_infer_type Γ P = None"
thus False using H by simp
qed
moreover have "ptrm_infer_type Γ P ≠ Some TUnit"
proof(rule classical, auto)
assume "ptrm_infer_type Γ P = Some TUnit"
thus False using H by simp
qed
moreover have "ptrm_infer_type Γ P ≠ Some (TVar x)" for x
proof(rule classical, auto)
assume "ptrm_infer_type Γ P = Some (TVar x)"
thus False using H by simp
qed
moreover have "ptrm_infer_type Γ P ≠ Some (TArr T S)" for T S
proof(rule classical, auto)
assume "ptrm_infer_type Γ P = Some (TArr T S)"
thus False using H by simp
qed
ultimately obtain T S where
"ptrm_infer_type Γ P = Some (TPair T S)"
using type.distinct type.exhaust option.exhaust by metis
moreover hence "ptrm_infer_type Γ (PFst P) = Some T" by simp
ultimately show "∃T S. ptrm_infer_type Γ P = Some (TPair T S) ∧ τ = T"
using H by auto
qed
lemma infer_sndE:
assumes "infer Γ (Snd P) = Some τ"
shows "∃T S. infer Γ P = Some (TPair T S) ∧ τ = S"
using assms proof(transfer)
fix P :: "'a ptrm" and Γ τ
assume H: "ptrm_infer_type Γ (PSnd P) = Some τ"
have "ptrm_infer_type Γ P ≠ None"
proof(rule classical, auto)
assume "ptrm_infer_type Γ P = None"
thus False using H by simp
qed
moreover have "ptrm_infer_type Γ P ≠ Some TUnit"
proof(rule classical, auto)
assume "ptrm_infer_type Γ P = Some TUnit"
thus False using H by simp
qed
moreover have "ptrm_infer_type Γ P ≠ Some (TVar x)" for x
proof(rule classical, auto)
assume "ptrm_infer_type Γ P = Some (TVar x)"
thus False using H by simp
qed
moreover have "ptrm_infer_type Γ P ≠ Some (TArr T S)" for T S
proof(rule classical, auto)
assume "ptrm_infer_type Γ P = Some (TArr T S)"
thus False using H by simp
qed
ultimately obtain T S where
"ptrm_infer_type Γ P = Some (TPair T S)"
using type.distinct type.exhaust option.exhaust by metis
moreover hence "ptrm_infer_type Γ (PSnd P) = Some S" by simp
ultimately show "∃T S. ptrm_infer_type Γ P = Some (TPair T S) ∧ τ = S"
using H by auto
qed
lemma infer_sound:
assumes "infer Γ M = Some τ"
shows "Γ ⊢ M : τ"
using assms proof(induction M arbitrary: Γ τ rule: trm_induct)
case 1
thus ?case using infer_unitE typing.tunit by metis
next
case (2 x)
hence "Γ x = Some τ" using infer_varE by metis
thus ?case using typing.tvar by metis
next
case (3 A B)
from ‹infer Γ (App A B) = Some τ› obtain σ
where "infer Γ A = Some (TArr σ τ)" and "infer Γ B = Some σ"
using infer_appE by metis
thus ?case using "3.IH" typing.tapp by metis
next
case (4 x T A Γ τ)
from ‹infer Γ (Fn x T A) = Some τ› obtain σ
where "τ = TArr T σ" and "infer (Γ(x ↦ T)) A = Some σ"
using infer_fnE by metis
thus ?case using "4.IH" typing.tfn by metis
next
case (5 A B Γ τ)
thus ?case using typing.tpair infer_pairE by metis
next
case (6 P Γ τ)
thus ?case using typing.tfst infer_fstE by metis
next
case (7 P Γ τ)
thus ?case using typing.tsnd infer_sndE by metis
next
qed
lemma infer_complete:
assumes "Γ ⊢ M : τ"
shows "infer Γ M = Some τ"
using assms proof(induction)
case (tfn Γ x τ A σ)
thus ?case by (simp add: infer_simp(4) tfn.IH)
next
qed (auto simp add: infer_simp)
theorem infer_valid:
shows "(Γ ⊢ M : τ) = (infer Γ M = Some τ)"
using infer_sound infer_complete by blast
inductive substitutes :: "'a trm ⇒ 'a ⇒ 'a trm ⇒ 'a trm ⇒ bool" where
unit: "substitutes Unit y M Unit"
| var1: "x = y ⟹ substitutes (Var x) y M M"
| var2: "x ≠ y ⟹ substitutes (Var x) y M (Var x)"
| app: "⟦substitutes A x M A'; substitutes B x M B'⟧ ⟹ substitutes (App A B) x M (App A' B')"
| fn: "⟦x ≠ y; y ∉ fvs M; substitutes A x M A'⟧ ⟹ substitutes (Fn y T A) x M (Fn y T A')"
| pair: "⟦substitutes A x M A'; substitutes B x M B'⟧ ⟹ substitutes (Pair A B) x M (Pair A' B')"
| fst: "substitutes P x M P' ⟹ substitutes (Fst P) x M (Fst P')"
| snd: "substitutes P x M P' ⟹ substitutes (Snd P) x M (Snd P')"
lemma substitutes_prm:
assumes "substitutes A x M A'"
shows "substitutes (π ⋅ A) (π $ x) (π ⋅ M) (π ⋅ A')"
using assms proof(induction)
case (unit y M)
thus ?case using substitutes.unit trm_prm_simp(1) by metis
case (var1 x y M)
thus ?case using substitutes.var1 trm_prm_simp(2) by metis
next
case (var2 x y M)
thus ?case using substitutes.var2 trm_prm_simp(2) prm_apply_unequal by metis
next
case (app A x M A' B B')
thus ?case using substitutes.app trm_prm_simp(3) by metis
next
case (fn x y M A A' T)
thus ?case
using substitutes.fn trm_prm_simp(4) prm_apply_unequal prm_set_notmembership trm_prm_fvs
by metis
next
case (pair A x M A' B B')
thus ?case using substitutes.pair trm_prm_simp(5) by metis
next
case (fst P x M P')
thus ?case using substitutes.fst trm_prm_simp(6) by metis
next
case (snd P x M P')
thus ?case using substitutes.snd trm_prm_simp(7) by metis
next
qed
lemma substitutes_fvs:
assumes "substitutes A x M A'"
shows "fvs A' ⊆ fvs A - {x} ∪ fvs M"
using assms proof(induction)
case (unit y M)
thus ?case using fvs_simp(1) by auto
case (var1 x y M)
thus ?case by auto
next
case (var2 x y M)
thus ?case
using fvs_simp(2) Un_subset_iff Un_upper2 insert_Diff_if insert_is_Un singletonD sup_commute
by metis
next
case (app A x M A' B B')
hence "fvs A' ∪ fvs B' ⊆ (fvs A - {x} ∪ fvs M) ∪ (fvs B - {x} ∪ fvs M)" by auto
hence "fvs A' ∪ fvs B' ⊆ (fvs A ∪ fvs B) - {x} ∪ fvs M" by auto
thus ?case using fvs_simp(3) by metis
next
case (fn x y M A A' T)
hence "fvs A' - {y} ⊆ fvs A - {y} - {x} ∪ fvs M" by auto
thus ?case using fvs_simp(4) by metis
next
case (pair A x M A' B B')
hence "fvs A' ∪ fvs B' ⊆ (fvs A - {x} ∪ fvs M) ∪ (fvs B - {x} ∪ fvs M)" by auto
hence "fvs A' ∪ fvs B' ⊆ (fvs A ∪ fvs B) - {x} ∪ fvs M" by auto
thus ?case using fvs_simp(5) by metis
next
case (fst P x M P')
thus ?case using fvs_simp(6) by fastforce
next
case (snd P x M P')
thus ?case using fvs_simp(7) by fastforce
next
qed
inductive_cases substitutes_unitE': "substitutes Unit y M X"
lemma substitutes_unitE:
assumes "substitutes Unit y M X"
shows "X = Unit"
by(
rule substitutes_unitE'[where y=y and M=M and X=X],
metis assms,
auto simp add: unit_not_var unit_not_app unit_not_fn unit_not_pair unit_not_fst unit_not_snd
)
inductive_cases substitutes_varE': "substitutes (Var x) y M X"
lemma substitutes_varE:
assumes "substitutes (Var x) y M X"
shows "(x = y ∧ M = X) ∨ (x ≠ y ∧ X = Var x)"
by(
rule substitutes_varE'[where x=x and y=y and M=M and X=X],
metis assms,
metis unit_not_var,
metis trm_simp(1),
metis trm_simp(1),
auto simp add: var_not_app var_not_fn var_not_pair var_not_fst var_not_snd
)
inductive_cases substitutes_appE': "substitutes (App A B) x M X"
lemma substitutes_appE:
assumes "substitutes (App A B) x M X"
shows "∃A' B'. substitutes A x M A' ∧ substitutes B x M B' ∧ X = App A' B'"
by(
cases rule: substitutes_appE'[where A=A and B=B and x=x and M=M and X=X],
metis assms,
metis unit_not_app,
metis var_not_app,
metis var_not_app,
metis trm_simp(2,3),
auto simp add: app_not_fn app_not_pair app_not_fst app_not_snd
)
inductive_cases substitutes_fnE': "substitutes (Fn y T A) x M X"
lemma substitutes_fnE:
assumes "substitutes (Fn y T A) x M X" "y ≠ x" "y ∉ fvs M"
shows "∃A'. substitutes A x M A' ∧ X = Fn y T A'"
using assms proof(induction rule: substitutes_fnE'[where y=y and T=T and A=A and x=x and M=M and X=X])
case (6 z B B' S)
consider "y = z ∧ T = S ∧ A = B" | "y ≠ z ∧ T = S ∧ y ∉ fvs B ∧ A = [y ↔ z] ⋅ B"
using ‹Fn y T A = Fn z S B› trm_simp(4) by metis
thus ?case proof(cases)
case 1
thus ?thesis using 6 by metis
next
case 2
hence "y ≠ z" "T = S" "y ∉ fvs B" "A = [y ↔ z] ⋅ B" by auto
have "substitutes ([y ↔ z] ⋅ B) ([y ↔ z] $ x) ([y ↔ z] ⋅ M) ([y ↔ z] ⋅ B')"
using substitutes_prm ‹substitutes B x M B'› by metis
hence "substitutes A ([y ↔ z] $ x) ([y ↔ z] ⋅ M) ([y ↔ z] ⋅ B')"
using ‹A = [y ↔ z] ⋅ B› by metis
hence "substitutes A x ([y ↔ z] ⋅ M) ([y ↔ z] ⋅ B')"
using ‹y ≠ x› ‹x ≠ z› prm_unit_inaction by metis
hence *: "substitutes A x M ([y ↔ z] ⋅ B')"
using ‹y ∉ fvs M› ‹z ∉ fvs M› trm_prm_unit_inaction by metis
have "y ∉ fvs B'"
using
substitutes_fvs ‹substitutes B x M B'› ‹y ∉ fvs B› ‹y ∉ fvs M›
Diff_subset UnE rev_subsetD
by blast
hence "X = Fn y T ([y ↔ z] ⋅ B')"
using ‹X = Fn z S B'› ‹y ≠ z› ‹T = S› fn_eq
by metis
thus ?thesis using * by auto
next
qed
next
qed (
metis assms(1),
metis unit_not_fn,
metis var_not_fn,
metis var_not_fn,
metis app_not_fn,
metis fn_not_pair,
metis fn_not_fst,
metis fn_not_snd
)
inductive_cases substitutes_pairE': "substitutes (Pair A B) x M X"
lemma substitutes_pairE:
assumes "substitutes (Pair A B) x M X"
shows "∃A' B'. substitutes A x M A' ∧ substitutes B x M B' ∧ X = Pair A' B'"
proof(cases rule: substitutes_pairE'[where A=A and B=B and x=x and M=M and X=X])
case (7 A A' B B')
thus ?thesis using trm_simp(5) trm_simp(6) by blast
next
qed (
metis assms,
metis unit_not_pair,
metis var_not_pair,
metis var_not_pair,
metis app_not_pair,
metis fn_not_pair,
metis pair_not_fst,
metis pair_not_snd
)
inductive_cases substitutes_fstE': "substitutes (Fst P) x M X"
lemma substitutes_fstE:
assumes "substitutes (Fst P) x M X"
shows "∃P'. substitutes P x M P' ∧ X = Fst P'"
proof(cases rule: substitutes_fstE'[where P=P and x=x and M=M and X=X])
case (8 P P')
thus ?thesis using trm_simp(7) by blast
next
qed (
metis assms,
metis unit_not_fst,
metis var_not_fst,
metis var_not_fst,
metis app_not_fst,
metis fn_not_fst,
metis pair_not_fst,
metis fst_not_snd
)
inductive_cases substitutes_sndE': "substitutes (Snd P) x M X"
lemma substitutes_sndE:
assumes "substitutes (Snd P) x M X"
shows "∃P'. substitutes P x M P' ∧ X = Snd P'"
proof(cases rule: substitutes_sndE'[where P=P and x=x and M=M and X=X])
case (9 P P')
thus ?thesis using trm_simp(8) by blast
next
qed (
metis assms,
metis unit_not_snd,
metis var_not_snd,
metis var_not_snd,
metis app_not_snd,
metis fn_not_snd,
metis pair_not_snd,
metis fst_not_snd
)
lemma substitutes_total:
shows "∃X. substitutes A x M X"
proof(induction A rule: trm_strong_induct[where S="{x} ∪ fvs M"])
show "finite ({x} ∪ fvs M)" using fvs_finite by auto
next
case 1
obtain X :: "'a trm" where "X = Unit" by auto
thus ?case using substitutes.unit by metis
next
case (2 y)
consider "x = y" | "x ≠ y" by auto
thus ?case proof(cases)
case 1
obtain X where "X = M" by auto
hence "substitutes (Var y) x M X" using ‹x = y› substitutes.var1 by metis
thus ?thesis by auto
next
case 2
obtain X where "X = (Var y)" by auto
hence "substitutes (Var y) x M X" using ‹x ≠ y› substitutes.var2 by metis
thus ?thesis by auto
next
qed
next
case (3 A B)
from this obtain A' B' where A': "substitutes A x M A'" and B': "substitutes B x M B'" by auto
obtain X where "X = App A' B'" by auto
hence "substitutes (App A B) x M X" using A' B' substitutes.app by metis
thus ?case by auto
next
case (4 y T A)
from this obtain A' where A': "substitutes A x M A'" by auto
from ‹y ∉ ({x} ∪ fvs M)› have "y ≠ x" "y ∉ fvs M" by auto
obtain X where "X = Fn y T A'" by auto
hence "substitutes (Fn y T A) x M X" using substitutes.fn ‹y ≠ x› ‹y ∉ fvs M› A' by metis
thus ?case by auto
next
case (5 A B)
from this obtain A' B' where "substitutes A x M A'" "substitutes B x M B'" by auto
from this obtain X where "X = Pair A' B'" by auto
hence "substitutes (Pair A B) x M X"
using substitutes.pair ‹substitutes A x M A'› ‹substitutes B x M B'›
by metis
thus ?case by auto
next
case (6 P)
from this obtain P' where "substitutes P x M P'" by auto
from this obtain X where "X = Fst P'" by auto
hence "substitutes (Fst P) x M X" using substitutes.fst ‹substitutes P x M P'› by metis
thus ?case by auto
next
case (7 P)
from this obtain P' where "substitutes P x M P'" by auto
from this obtain X where "X = Snd P'" by auto
hence "substitutes (Snd P) x M X" using substitutes.snd ‹substitutes P x M P'› by metis
thus ?case by auto
next
qed
lemma substitutes_unique:
assumes "substitutes A x M B" "substitutes A x M C"
shows "B = C"
using assms proof(induction A arbitrary: B C rule: trm_strong_induct[where S="{x} ∪ fvs M"])
show "finite ({x} ∪ fvs M)" using fvs_finite by auto
next
case 1
thus ?case using substitutes_unitE by metis
next
case (2 y)
thus ?case using substitutes_varE by metis
next
case (3 X Y)
thus ?case using substitutes_appE by metis
next
case (4 y T A)
hence "y ≠ x" and "y ∉ fvs M" by auto
thus ?case using 4 substitutes_fnE by metis
next
case (5 A B C D)
thus ?case using substitutes_pairE by metis
next
case (6 P Q R)
thus ?case using substitutes_fstE by metis
next
case (7 P Q R)
thus ?case using substitutes_sndE by metis
next
qed
lemma substitutes_function:
shows "∃! X. substitutes A x M X"
using substitutes_total substitutes_unique by metis
definition subst :: "'a trm ⇒ 'a ⇒ 'a trm ⇒ 'a trm" ("_[_ ::= _]") where
"subst A x M ≡ (THE X. substitutes A x M X)"
lemma subst_simp_unit:
shows "Unit[x ::= M] = Unit"
unfolding subst_def by(rule, metis substitutes.unit, metis substitutes_function substitutes.unit)
lemma subst_simp_var1:
shows "(Var x)[x ::= M] = M"
unfolding subst_def by(rule, metis substitutes.var1, metis substitutes_function substitutes.var1)
lemma subst_simp_var2:
assumes "x ≠ y"
shows "(Var x)[y ::= M] = Var x"
unfolding subst_def by(
rule,
metis substitutes.var2 assms,
metis substitutes_function substitutes.var2 assms
)
lemma subst_simp_app:
shows "(App A B)[x ::= M] = App (A[x ::= M]) (B[x ::= M])"
unfolding subst_def proof
obtain A' B' where A': "A' = (A[x ::= M])" and B': "B' = (B[x ::= M])" by auto
hence "substitutes A x M A'" "substitutes B x M B'"
unfolding subst_def
using substitutes_function theI by metis+
hence "substitutes (App A B) x M (App A' B')" using substitutes.app by metis
thus *: "substitutes (App A B) x M (App (THE X. substitutes A x M X) (THE X. substitutes B x M X))"
using A' B' unfolding subst_def by metis
fix X
assume "substitutes (App A B) x M X"
thus "X = App (THE X. substitutes A x M X) (THE X. substitutes B x M X)"
using substitutes_function * by metis
qed
lemma subst_simp_fn:
assumes "x ≠ y" "y ∉ fvs M"
shows "(Fn y T A)[x ::= M] = Fn y T (A[x ::= M])"
unfolding subst_def proof
obtain A' where A': "A' = (A[x ::= M])" by auto
hence "substitutes A x M A'" unfolding subst_def using substitutes_function theI by metis
hence "substitutes (Fn y T A) x M (Fn y T A')" using substitutes.fn assms by metis
thus *: "substitutes (Fn y T A) x M (Fn y T (THE X. substitutes A x M X))"
using A' unfolding subst_def by metis
fix X
assume "substitutes (Fn y T A) x M X"
thus "X = Fn y T (THE X. substitutes A x M X)" using substitutes_function * by metis
qed
lemma subst_simp_pair:
shows "(Pair A B)[x ::= M] = Pair (A[x ::= M]) (B[x ::= M])"
unfolding subst_def proof
obtain A' B' where A': "A' = (A[x ::= M])" and B': "B' = (B[x ::= M])" by auto
hence "substitutes A x M A'" "substitutes B x M B'"
unfolding subst_def using substitutes_function theI by metis+
hence "substitutes (Pair A B) x M (Pair A' B')" using substitutes.pair by metis
thus *: "substitutes (Pair A B) x M (Pair (THE X. substitutes A x M X) (THE X. substitutes B x M X))"
using A' B' unfolding subst_def by metis
fix X
assume "substitutes (Pair A B) x M X"
thus "X = Pair (THE X. substitutes A x M X) (THE X. substitutes B x M X)"
using substitutes_function * by metis
qed
lemma subst_simp_fst:
shows "(Fst P)[x ::= M] = Fst (P[x ::= M])"
unfolding subst_def proof
obtain P' where P': "P' = (P[x ::= M])" by auto
hence "substitutes P x M P'" unfolding subst_def using substitutes_function theI by metis
hence "substitutes (Fst P) x M (Fst P')" using substitutes.fst by metis
thus *: "substitutes (Fst P) x M (Fst (THE X. substitutes P x M X))"
using P' unfolding subst_def by metis
fix X
assume "substitutes (Fst P) x M X"
thus "X = Fst (THE X. substitutes P x M X)" using substitutes_function * by metis
qed
lemma subst_simp_snd:
shows "(Snd P)[x ::= M] = Snd (P[x ::= M])"
unfolding subst_def proof
obtain P' where P': "P' = (P[x ::= M])" by auto
hence "substitutes P x M P'" unfolding subst_def using substitutes_function theI by metis
hence "substitutes (Snd P) x M (Snd P')" using substitutes.snd by metis
thus *: "substitutes (Snd P) x M (Snd (THE X. substitutes P x M X))"
using P' unfolding subst_def by metis
fix X
assume "substitutes (Snd P) x M X"
thus "X = Snd (THE X. substitutes P x M X)" using substitutes_function * by metis
qed
lemma subst_prm:
shows "(π ⋅ (M[z ::= N])) = ((π ⋅ M)[π $ z ::= π ⋅ N])"
unfolding subst_def using substitutes_prm substitutes_function the1_equality by (metis (full_types))
lemma subst_fvs:
shows "fvs (M[z ::= N]) ⊆ (fvs M - {z}) ∪ fvs N"
unfolding subst_def using substitutes_fvs substitutes_function theI2 by metis
lemma subst_free:
assumes "y ∉ fvs M"
shows "M[y ::= N] = M"
using assms proof(induction M rule: trm_strong_induct[where S="{y} ∪ fvs N"])
show "finite ({y} ∪ fvs N)" using fvs_finite by auto
case 1
thus ?case using subst_simp_unit by metis
next
case (2 x)
thus ?case using subst_simp_var2 by (simp add: fvs_simp)
next
case (3 A B)
thus ?case using subst_simp_app by (simp add: fvs_simp)
next
case (4 x T A)
hence "y ≠ x" "x ∉ fvs N" by auto
have "y ∉ fvs A - {x}" using ‹y ≠ x› ‹y ∉ fvs (Fn x T A)› fvs_simp(4) by metis
hence "y ∉ fvs A" using ‹y ≠ x› by auto
hence "A[y ::= N] = A" using "4.IH" by blast
thus ?case using ‹y ≠ x› ‹y ∉ fvs A› ‹x ∉ fvs N› subst_simp_fn by metis
next
case (5 A B)
thus ?case using subst_simp_pair by (simp add: fvs_simp)
next
case (6 P)
thus ?case using subst_simp_fst by (simp add: fvs_simp)
next
case (7 P)
thus ?case using subst_simp_snd by (simp add: fvs_simp)
next
qed
lemma subst_swp:
assumes "y ∉ fvs A"
shows "([y ↔ z] ⋅ A)[y ::= M] = (A[z ::= M])"
using assms proof(induction A rule: trm_strong_induct[where S="{y, z} ∪ fvs M"])
show "finite ({y, z} ∪ fvs M)" using fvs_finite by auto
next
case 1
thus ?case using trm_prm_simp(1) subst_simp_unit by metis
next
case (2 x)
hence "y ≠ x" using fvs_simp(2) by force
consider "x = z" | "x ≠ z" by auto
thus ?case proof(cases)
case 1
thus ?thesis using subst_simp_var1 trm_prm_simp(2) prm_unit_action prm_unit_commutes by metis
next
case 2
thus ?thesis using subst_simp_var2 trm_prm_simp(2) prm_unit_inaction ‹y ≠ x› by metis
next
qed
next
case (3 A B)
from ‹y ∉ fvs (App A B)› have "y ∉ fvs A" "y ∉ fvs B" by (auto simp add: fvs_simp(3))
thus ?case using "3.IH" subst_simp_app trm_prm_simp(3) by metis
next
case (4 x T A)
hence "x ≠ y" "x ≠ z" "x ∉ fvs M"