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" by auto
hence "y ∉ fvs A" using ‹y ∉ fvs (Fn x T A)› fvs_simp(4) by force
hence *: "([y ↔ z] ⋅ A)[y ::= M] = (A[z ::= M])" using "4.IH" by metis
have "([y ↔ z] ⋅ Fn x T A)[y ::= M] = ((Fn ([y ↔ z] $ x) T ([y ↔ z] ⋅ A))[y ::= M])"
using trm_prm_simp(4) by metis
also have "... = ((Fn x T ([y ↔ z] ⋅ A))[y ::= M])"
using prm_unit_inaction ‹x ≠ y› ‹x ≠ z› by metis
also have "... = Fn x T (([y ↔ z] ⋅ A)[y ::= M])"
using subst_simp_fn ‹x ≠ y› ‹x ∉ fvs M› by metis
also have "... = Fn x T (A[z ::= M])" using * by metis
also have "... = ((Fn x T A)[z ::= M])"
using subst_simp_fn ‹x ≠ z› ‹x ∉ fvs M› by metis
finally show ?case.
next
case (5 A B)
from ‹y ∉ fvs (Pair A B)› have "y ∉ fvs A" "y ∉ fvs B" by (auto simp add: fvs_simp(5))
hence "([y ↔ z] ⋅ A)[y ::= M] = (A[z ::= M])" "([y ↔ z] ⋅ B)[y ::= M] = (B[z ::= M])"
using "5.IH" by metis+
thus ?case using trm_prm_simp(5) subst_simp_pair by metis
next
case (6 P)
from ‹y ∉ fvs (Fst P)› have "y ∉ fvs P" by (simp add: fvs_simp(6))
hence "([y ↔ z] ⋅ P)[y ::= M] = (P[z ::= M])" using "6.IH" by metis
thus ?case using trm_prm_simp(6) subst_simp_fst by metis
next
case (7 P)
from ‹y ∉ fvs (Snd P)› have "y ∉ fvs P" by (simp add: fvs_simp(7))
hence "([y ↔ z] ⋅ P)[y ::= M] = (P[z ::= M])" using "7.IH" by metis
thus ?case using trm_prm_simp(7) subst_simp_snd by metis
next
qed
lemma barendregt:
assumes "y ≠ z" "y ∉ fvs L"
shows "M[y ::= N][z ::= L] = (M[z ::= L][y ::= N[z ::= L]])"
using assms proof(induction M rule: trm_strong_induct[where S="{y, z} ∪ fvs N ∪ fvs L"])
show "finite ({y, z} ∪ fvs N ∪ fvs L)" using fvs_finite by auto
next
case 1
thus ?case using subst_simp_unit by metis
next
case (2 x)
consider "x = y" | "x = z" | "x ≠ y ∧ x ≠ z" by auto
thus ?case proof(cases)
case 1
hence "x = y" "x ≠ z" using assms(1) by auto
thus ?thesis using subst_simp_var1 subst_simp_var2 by metis
next
case 2
hence "x ≠ y" "x = z" using assms(1) by auto
thus ?thesis using subst_free ‹y ∉ fvs L› subst_simp_var1 subst_simp_var2 by metis
next
case 3
then show ?thesis using subst_simp_var2 by metis
next
qed
next
case (3 A B)
thus ?case using subst_simp_app by metis
next
case (4 x T A)
hence *: "A[y ::= N][z ::= L] = (A[z ::= L][y ::= N[z ::= L]])" by blast
from ‹x ∉ {y, z} ∪ fvs N ∪ fvs L› have "x ≠ y" "x ≠ z" "x ∉ fvs N" "x ∉ fvs L" by auto
hence "x ∉ fvs (N[z ::= L])" using subst_fvs by auto
have "(Fn x T A)[y ::= N][z ::= L] = Fn x T (A[y ::= N][z ::= L])"
using subst_simp_fn ‹x ≠ y› ‹x ≠ z› ‹x ∉ fvs N› ‹x ∉ fvs L› by metis
also have "... = Fn x T (A[z ::= L][y ::= N[z ::= L]])" using * by metis
also have "... = ((Fn x T A)[z ::= L][y ::= N[z ::= L]])"
using subst_simp_fn ‹x ≠ y› ‹x ≠ z› ‹x ∉ fvs (N[z ::= L])› ‹x ∉ fvs L› by metis
finally show ?case.
next
case (5 A B)
thus ?case using subst_simp_pair by metis
next
case (6 P)
thus ?case using subst_simp_fst by metis
next
case (7 P)
thus ?case using subst_simp_snd by metis
next
qed
lemma typing_subst:
assumes "Γ(z ↦ τ) ⊢ M : σ" "Γ ⊢ N : τ"
shows "Γ ⊢ M[z ::= N] : σ"
using assms proof(induction M arbitrary: Γ σ rule: trm_strong_depth_induct[where S="{z} ∪ fvs N"])
show "finite ({z} ∪ fvs N)" using fvs_finite by auto
next
case 1
thus ?case using subst_simp_unit typing.tunit typing_unitE by metis
next
case (2 x)
hence *: "(Γ(z ↦ τ)) x = Some σ" using typing_varE by metis
consider "x = z" | "x ≠ z" by auto
thus ?case proof(cases)
case 1
hence "(Γ(x ↦ τ)) x = Some σ" using * by metis
hence "τ = σ" by auto
thus ?thesis using ‹Γ ⊢ N : τ› subst_simp_var1 ‹x = z› by metis
next
case 2
hence "Γ x = Some σ" using * by auto
hence "Γ ⊢ Var x : σ" using typing.tvar by metis
thus ?thesis using ‹x ≠ z› subst_simp_var2 by metis
next
qed
next
case (3 A B)
have *: "depth A < depth (App A B) ∧ depth B < depth (App A B)"
using depth_app by auto
from ‹Γ(z ↦ τ) ⊢ App A B : σ› obtain σ' where
"Γ(z ↦ τ) ⊢ A : (TArr σ' σ)"
"Γ(z ↦ τ) ⊢ B : σ'"
using typing_appE by metis
hence
"Γ ⊢ (A[z ::= N]) : (TArr σ' σ)"
"Γ ⊢ (B[z ::= N]) : σ'"
using 3 * by metis+
hence "Γ ⊢ App (A[z ::= N]) (B[z ::= N]) : σ" using typing.tapp by metis
thus ?case using subst_simp_app by metis
next
case (4 x T A)
hence "x ≠ z" "x ∉ fvs N" by auto
hence *: "Γ(x ↦ T) ⊢ N : τ" using typing_weaken 4 by metis
have **: "depth A < depth (Fn x T A)" using depth_fn.
from ‹Γ(z ↦ τ) ⊢ Fn x T A : σ› obtain σ' where
"σ = TArr T σ'"
"Γ(z ↦ τ, x ↦ T) ⊢ A : σ'"
using typing_fnE by metis
hence "Γ(x ↦ T, z ↦ τ) ⊢ A : σ'" using ‹x ≠ z› fun_upd_twist by metis
hence "Γ(x ↦ T) ⊢ A[z ::= N] : σ'" using 4 * ** by metis
hence "Γ ⊢ Fn x T (A[z ::= N]) : σ" using typing.tfn ‹σ = TArr T σ'› by metis
thus ?case using ‹x ≠ z› ‹x ∉ fvs N› subst_simp_fn by metis
next
case (5 A B)
from this obtain T S where "σ = TPair T S" "Γ(z ↦ τ) ⊢ A : T" "Γ(z ↦ τ) ⊢ B : S"
using typing_pairE by metis
moreover have "depth A < depth (Pair A B)" and "depth B < depth (Pair A B)"
using depth_pair by auto
ultimately have "Γ ⊢ A[z ::= N] : T" "Γ ⊢ B[z ::= N] : S" using 5 by metis+
hence "Γ ⊢ Pair (A[z ::= N]) (B[z ::= N]) : σ" using ‹σ = TPair T S› typing.tpair by metis
thus ?case using subst_simp_pair by metis
next
case (6 P)
from this obtain σ' where "Γ(z ↦ τ) ⊢ P : (TPair σ σ')" using typing_fstE by metis
moreover have "depth P < depth (Fst P)" using depth_fst by metis
ultimately have "Γ ⊢ P[z ::= N] : (TPair σ σ')" using 6 by metis
hence "Γ ⊢ Fst (P[z ::= N]) : σ" using typing.tfst by metis
thus ?case using subst_simp_fst by metis
next
case (7 P)
from this obtain σ' where "Γ(z ↦ τ) ⊢ P : (TPair σ' σ)" using typing_sndE by metis
moreover have "depth P < depth (Snd P)" using depth_snd by metis
ultimately have "Γ ⊢ P[z ::= N] : (TPair σ' σ)" using 7 by metis
hence "Γ ⊢ Snd (P[z ::= N]) : σ" using typing.tsnd by metis
thus ?case using subst_simp_snd by metis
next
qed
inductive beta_reduction :: "'a trm ⇒ 'a trm ⇒ bool" ("_ →β _") where
beta: "(App (Fn x T A) M) →β (A[x ::= M])"
| app1: "A →β A' ⟹ (App A B) →β (App A' B)"
| app2: "B →β B' ⟹ (App A B) →β (App A B')"
| fn: "A →β A' ⟹ (Fn x T A) →β (Fn x T A')"
| pair1: "A →β A' ⟹ (Pair A B) →β (Pair A' B)"
| pair2: "B →β B' ⟹ (Pair A B) →β (Pair A B')"
| fst1: "P →β P' ⟹ (Fst P) →β (Fst P')"
| fst2: "(Fst (Pair A B)) →β A"
| snd1: "P →β P' ⟹ (Snd P) →β (Snd P')"
| snd2: "(Snd (Pair A B)) →β B"
lemma beta_reduction_fvs:
assumes "M →β M'"
shows "fvs M' ⊆ fvs M"
using assms proof(induction)
case (beta x T A M)
thus ?case using fvs_simp(3) fvs_simp(4) subst_fvs by metis
next
case (app1 A A' B)
hence "fvs A' ∪ fvs B ⊆ fvs A ∪ fvs B" by auto
thus ?case using fvs_simp(3) by metis
next
case (app2 B B' A)
hence "fvs A ∪ fvs B' ⊆ fvs A ∪ fvs B" by auto
thus ?case using fvs_simp(3) by metis
next
case (fn A A' x T)
hence "fvs A' - {x} ⊆ fvs A - {x}" by auto
thus ?case using fvs_simp(4) by metis
next
case (pair1 A A' B)
hence "fvs A' ∪ fvs B ⊆ fvs A ∪ fvs B" by auto
thus ?case using fvs_simp(5) by metis
next
case (pair2 B B' A)
hence "fvs A ∪ fvs B' ⊆ fvs A ∪ fvs B" by auto
thus ?case using fvs_simp(5) by metis
next
case (fst1 P P')
thus ?case using fvs_simp(6) by metis
next
case (fst2 A B)
thus ?case using fvs_simp(5, 6) by force
next
case (snd1 P P')
thus ?case using fvs_simp(7) by metis
next
case (snd2 A B)
thus ?case using fvs_simp(5, 7) by force
next
qed
lemma beta_reduction_prm:
assumes "M →β M'"
shows "(π ⋅ M) →β (π ⋅ M')"
using assms by(induction, auto simp add: beta_reduction.intros trm_prm_simp subst_prm)
lemma beta_reduction_left_unitE:
assumes "Unit →β M'"
shows "False"
using assms by(cases, auto simp add: unit_not_app unit_not_fn unit_not_pair unit_not_fst unit_not_snd)
lemma beta_reduction_left_varE:
assumes "(Var x) →β M'"
shows "False"
using assms by(cases, auto simp add: var_not_app var_not_fn var_not_pair var_not_fst var_not_snd)
lemma beta_reduction_left_appE:
assumes "(App A B) →β M'"
shows "
(∃x T X. A = (Fn x T X) ∧ M' = (X[x ::= B])) ∨
(∃A'. (A →β A') ∧ M' = App A' B) ∨
(∃B'. (B →β B') ∧ M' = App A B')
"
using assms by(
cases,
metis trm_simp(2, 3),
metis trm_simp(2, 3),
metis trm_simp(2, 3),
auto simp add: app_not_fn app_not_pair app_not_fst app_not_snd
)
lemma beta_reduction_left_fnE:
assumes "(Fn x T A) →β M'"
shows "∃A'. (A →β A') ∧ M' = (Fn x T A')"
using assms proof(cases)
case (fn B B' y S)
consider "x = y ∧ T = S ∧ A = B" | "x ≠ y ∧ T = S ∧ x ∉ fvs B ∧ A = [x ↔ y] ⋅ B"
using trm_simp(4) ‹Fn x T A = Fn y S B› by metis
thus ?thesis proof(cases)
case 1
thus ?thesis using fn by auto
next
case 2
thus ?thesis using fn beta_reduction_fvs beta_reduction_prm fn_eq by fastforce
next
qed
next
qed (
metis app_not_fn,
metis app_not_fn,
metis app_not_fn,
auto simp add: fn_not_pair fn_not_fst fn_not_snd
)
lemma beta_reduction_left_pairE:
assumes "(Pair A B) →β M'"
shows "(∃A'. (A →β A') ∧ M' = (Pair A' B)) ∨ (∃B'. (B →β B') ∧ M' = (Pair A B'))"
using assms
apply cases
prefer 5
apply (metis trm_simp(5, 6))
prefer 5
apply (metis trm_simp(5, 6))
apply (metis app_not_pair, metis app_not_pair, metis app_not_pair, metis fn_not_pair, metis pair_not_fst, metis pair_not_fst, metis pair_not_snd, metis pair_not_snd)
done
lemma beta_reduction_left_fstE:
assumes "(Fst P) →β M'"
shows "(∃P'. (P →β P') ∧ M' = (Fst P')) ∨ (∃A B. P = (Pair A B) ∧ M' = A)"
using assms proof(cases)
case (fst1 P P')
thus ?thesis using trm_simp(7) by blast
next
case (fst2 B)
thus ?thesis using trm_simp(7) by blast
next
qed (
metis app_not_fst,
metis app_not_fst,
metis app_not_fst,
metis fn_not_fst,
metis pair_not_fst,
metis pair_not_fst,
metis fst_not_snd,
metis fst_not_snd
)
lemma beta_reduction_left_sndE:
assumes "(Snd P) →β M'"
shows "(∃P'. (P →β P') ∧ M' = (Snd P')) ∨ (∃A B. P = Pair A B ∧ M' = B)"
using assms proof(cases)
case (snd1 P P')
thus ?thesis using trm_simp(8) by blast
next
case (snd2 A)
thus ?thesis using trm_simp(8) by blast
next
qed (
metis app_not_snd,
metis app_not_snd,
metis app_not_snd,
metis fn_not_snd,
metis pair_not_snd,
metis pair_not_snd,
metis fst_not_snd,
metis fst_not_snd
)
lemma preservation':
assumes "Γ ⊢ M : τ" and "M →β M'"
shows "Γ ⊢ M' : τ"
using assms proof(induction arbitrary: M' rule: typing.induct)
case (tunit Γ)
thus ?case using beta_reduction_left_unitE by metis
next
case (tvar Γ x τ)
thus ?case using beta_reduction_left_varE by metis
next
case (tapp Γ A τ σ B M')
from ‹(App A B) →β M'› consider
"(∃x T X. A = (Fn x T X) ∧ M' = (X[x ::= B]))" |
"(∃A'. (A →β A') ∧ M' = App A' B)" |
"(∃B'. (B →β B') ∧ M' = App A B')" using beta_reduction_left_appE by metis
thus ?case proof(cases)
case 1
from this obtain x T X where "A = Fn x T X" and *: "M' = (X[x ::= B])" by auto
have "Γ(x ↦ τ) ⊢ X : σ" using typing_fnE ‹Γ ⊢ A : (TArr τ σ)› ‹A = Fn x T X› type.inject
by blast
hence "Γ ⊢ (X[x ::= B]) : σ" using typing_subst ‹Γ ⊢ B : τ› by metis
thus ?thesis using * by auto
next
case 2
from this obtain A' where "A →β A'" and *: "M' = (App A' B)" by auto
hence "Γ ⊢ A' : (TArr τ σ)" using tapp.IH(1) by metis
hence "Γ ⊢ (App A' B) : σ" using ‹Γ ⊢ B : τ› typing.tapp by metis
thus ?thesis using * by auto
next
case 3
from this obtain B' where "B →β B'" and *: "M' = (App A B')" by auto
hence "Γ ⊢ B' : τ" using tapp.IH(2) by metis
hence "Γ ⊢ (App A B') : σ" using ‹Γ ⊢ A : (TArr τ σ)› typing.tapp by metis
thus ?thesis using * by auto
next
qed
next
case (tfn Γ x T A σ)
from this obtain A' where "A →β A'" and *: "M' = (Fn x T A')"
using beta_reduction_left_fnE by metis
hence "Γ(x ↦ T) ⊢ A' : σ" using tfn.IH by metis
hence "Γ ⊢ (Fn x T A') : (TArr T σ)" using typing.tfn by metis
thus ?case using * by auto
next
case (tpair Γ A τ B σ)
from this consider
"∃A'. (A →β A') ∧ M' = (Pair A' B)"
| "∃B'. (B →β B') ∧ M' = (Pair A B')"
using beta_reduction_left_pairE by metis
thus ?case proof(cases)
case 1
from this obtain A' where "A →β A'" and "M' = Pair A' B" by auto
thus ?thesis using tpair typing.tpair by metis
next
case 2
from this obtain B' where "B →β B'" and "M' = Pair A B'" by auto
thus ?thesis using tpair typing.tpair by metis
next
qed
next
case (tfst Γ P τ σ)
from this consider
"∃P'. (P →β P') ∧ M' = Fst P'"
| "∃A B. P = Pair A B ∧ M' = A" using beta_reduction_left_fstE by metis
thus ?case proof(cases)
case 1
from this obtain P' where "P →β P'" and "M' = Fst P'" by auto
thus ?thesis using tfst typing.tfst by metis
next
case 2
from this obtain A B where "P = Pair A B" and "M' = A" by auto
thus ?thesis using ‹Γ ⊢ P : (TPair τ σ)› typing_pairE by blast
next
qed
next
case (tsnd Γ P τ σ)
from this consider
"∃P'. (P →β P') ∧ M' = Snd P'"
| "∃A B. P = Pair A B ∧ M' = B" using beta_reduction_left_sndE by metis
thus ?case proof(cases)
case 1
from this obtain P' where "P →β P'" and "M' = Snd P'" by auto
thus ?thesis using tsnd typing.tsnd by metis
next
case 2
from this obtain A B where "P = Pair A B" and "M' = B" by auto
thus ?thesis using ‹Γ ⊢ P : (TPair τ σ)› typing_pairE by blast
next
qed
next
qed
inductive NF :: "'a trm ⇒ bool" where
unit: "NF Unit"
| var: "NF (Var x)"
| app: "⟦A ≠ Fn x T A'; NF A; NF B⟧ ⟹ NF (App A B)"
| fn: "NF A ⟹ NF (Fn x T A)"
| pair: "⟦NF A; NF B⟧ ⟹ NF (Pair A B)"
| fst: "⟦P ≠ Pair A B; NF P⟧ ⟹ NF (Fst P)"
| snd: "⟦P ≠ Pair A B; NF P⟧ ⟹ NF (Snd P)"
theorem progress:
assumes "Γ ⊢ M : τ"
shows "NF M ∨ (∃M'. (M →β M'))"
using assms proof(induction M arbitrary: Γ τ rule: trm_induct)
case 1
thus ?case using NF.unit by metis
next
case (2 x)
thus ?case using NF.var by metis
next
case (3 A B)
from ‹Γ ⊢ App A B : τ› obtain σ
where "Γ ⊢ A : (TArr σ τ)" and "Γ ⊢ B : σ"
using typing_appE by metis
hence A: "NF A ∨ (∃A'. (A →β A'))" and B: "NF B ∨ (∃B'. (B →β B'))"
using "3.IH" by auto
consider "NF B" | "∃B'. (B →β B')" using B by auto
thus ?case proof(cases)
case 1
consider "NF A" | "∃A'. (A →β A')" using A by auto
thus ?thesis proof(cases)
case 1
consider "∃x T A'. A = Fn x T A'" | "∄x T A'. A = Fn x T A'" by auto
thus ?thesis proof(cases)
case 1
from this obtain x T A' where "A = Fn x T A'" by auto
hence "(App A B) →β (A'[x ::= B])" using beta_reduction.beta by metis
thus ?thesis by blast
next
case 2
thus ?thesis using ‹NF A› ‹NF B› NF.app by metis
next
qed
next
case 2
thus ?thesis using beta_reduction.app1 by metis
next
qed
next
case 2
thus ?thesis using beta_reduction.app2 by metis
next
qed
next
case (4 x T A)
from ‹Γ ⊢ Fn x T A : τ› obtain σ
where "τ = TArr T σ" and "Γ(x ↦ T) ⊢ A : σ"
using typing_fnE by metis
from ‹Γ(x ↦ T) ⊢ A : σ› consider "NF A" | "∃A'. (A →β A')"
using "4.IH" by metis
thus ?case proof(cases)
case 1
thus ?thesis using NF.fn by metis
next
case 2
from this obtain A' where "A →β A'" by auto
obtain M' where "M' = Fn x T A'" by auto
hence "(Fn x T A) →β M'" using ‹A →β A'› beta_reduction.fn by metis
thus ?thesis by auto
next
qed
next
case (5 A B)
thus ?case using typing_pairE beta_reduction.pair1 beta_reduction.pair2 NF.pair by meson
next
case (6 P)
from this consider "NF P" | "∃P'. (P →β P')" using typing_fstE by metis
thus ?case proof(cases)
case 1
consider "∃A B. P = Pair A B" | "∄A B. P = Pair A B" by auto
thus ?thesis proof(cases)
case 1
from this obtain A B where "P = Pair A B" by auto
hence "(Fst P) →β A" using beta_reduction.fst2 by metis
thus ?thesis by auto
next
case 2
thus ?thesis using ‹NF P› NF.fst by metis
next
qed
next
case 2
thus ?thesis using beta_reduction.fst1 by metis
next
qed
next
case (7 P)
from this consider "NF P" | "∃P'. (P →β P')" using typing_sndE by metis
thus ?case proof(cases)
case 1
consider "∃A B. P = Pair A B" | "∄A B. P = Pair A B" by auto
thus ?thesis proof(cases)
case 1
from this obtain A B where "P = Pair A B" by auto
hence "(Snd P) →β B" using beta_reduction.snd2 by metis
thus ?thesis by auto
next
case 2
thus ?thesis using ‹NF P› NF.snd by metis
next
qed
next
case 2
thus ?thesis using beta_reduction.snd1 by metis
next
qed
next
qed
inductive beta_reduces :: "'a trm ⇒ 'a trm ⇒ bool" ("_ →β⇧* _") where
reflexive: "M →β⇧* M"
| transitive: "⟦M →β⇧* M'; M' →β M''⟧ ⟹ M →β⇧* M''"
lemma beta_reduces_composition:
assumes "A' →β⇧* A''" and "A →β⇧* A'"
shows "A →β⇧* A''"
using assms proof(induction)
case (reflexive B)
thus ?case.
next
case (transitive B B' B'')
thus ?case using beta_reduces.transitive by metis
next
qed
lemma beta_reduces_fvs:
assumes "A →β⇧* A'"
shows "fvs A' ⊆ fvs A"
using assms proof(induction)
case (reflexive M)
thus ?case by auto
next
case (transitive M M' M'')
hence "fvs M'' ⊆ fvs M'" using beta_reduction_fvs by metis
thus ?case using ‹fvs M' ⊆ fvs M› by auto
next
qed
lemma beta_reduces_app_left:
assumes "A →β⇧* A'"
shows "(App A B) →β⇧* (App A' B)"
using assms proof(induction)
case (reflexive A)
thus ?case using beta_reduces.reflexive.
next
case (transitive A A' A'')
thus ?case using beta_reduces.transitive beta_reduction.app1 by metis
next
qed
lemma beta_reduces_app_right:
assumes "B →β⇧* B'"
shows "(App A B) →β⇧* (App A B')"
using assms proof(induction)
case (reflexive B)
thus ?case using beta_reduces.reflexive.
next
case (transitive B B' B'')
thus ?case using beta_reduces.transitive beta_reduction.app2 by metis
next
qed
lemma beta_reduces_fn:
assumes "A →β⇧* A'"
shows "(Fn x T A) →β⇧* (Fn x T A')"
using assms proof(induction)
case (reflexive A)
thus ?case using beta_reduces.reflexive.
next
case (transitive A A' A'')
thus ?case using beta_reduces.transitive beta_reduction.fn by metis
next
qed
lemma beta_reduces_pair_left:
assumes "A →β⇧* A'"
shows "(Pair A B) →β⇧* (Pair A' B)"
using assms proof(induction)
case (reflexive M)
thus ?case using beta_reduces.reflexive.
next
case (transitive M M' M'')
thus ?case using beta_reduces.transitive beta_reduction.pair1 by metis
next
qed
lemma beta_reduces_pair_right:
assumes "B →β⇧* B'"
shows "(Pair A B) →β⇧* (Pair A B')"
using assms proof(induction)
case (reflexive M)
thus ?case using beta_reduces.reflexive.
next
case (transitive M M' M'')
thus ?case using beta_reduces.transitive beta_reduction.pair2 by metis
next
qed
lemma beta_reduces_fst:
assumes "P →β⇧* P'"
shows "(Fst P) →β⇧* (Fst P')"
using assms proof(induction)
case (reflexive M)
thus ?case using beta_reduces.reflexive.
next
case (transitive M M' M'')
thus ?case using beta_reduces.transitive beta_reduction.fst1 by metis
next
qed
lemma beta_reduces_snd:
assumes "P →β⇧* P'"
shows "(Snd P) →β⇧* (Snd P')"
using assms proof(induction)
case (reflexive M)
thus ?case using beta_reduces.reflexive.
next
case (transitive M M' M'')
thus ?case using beta_reduces.transitive beta_reduction.snd1 by metis
next
qed
theorem preservation:
assumes "M →β⇧* M'" "Γ ⊢ M : τ"
shows "Γ ⊢ M' : τ"
using assms proof(induction)
case (reflexive M)
thus ?case.
next
case (transitive M M' M'')
thus ?case using preservation' by metis
next
qed
theorem safety:
assumes "M →β⇧* M'" "Γ ⊢ M : τ"
shows "NF M' ∨ (∃M''. (M' →β M''))"
using assms proof(induction)
case (reflexive M)
thus ?case using progress by metis
next
case (transitive M M' M'')
hence "Γ ⊢ M' : τ" using preservation by metis
hence "Γ ⊢ M'' : τ" using preservation' ‹M' →β M''› by metis
thus ?case using progress by metis
next
qed
inductive parallel_reduction :: "'a trm ⇒ 'a trm ⇒ bool" ("_ >> _") where
refl: "A >> A"
| beta: "⟦A >> A'; B >> B'⟧ ⟹ (App (Fn x T A) B) >> (A'[x ::= B'])"
| eta: "A >> A' ⟹ (Fn x T A) >> (Fn x T A')"
| app: "⟦A >> A'; B >> B'⟧ ⟹ (App A B) >> (App A' B')"
| pair: "⟦A >> A'; B >> B'⟧ ⟹ (Pair A B) >> (Pair A' B')"
| fst1: "P >> P' ⟹ (Fst P) >> (Fst P')"
| fst2: "A >> A' ⟹ (Fst (Pair A B)) >> A'"
| snd1: "P >> P' ⟹ (Snd P) >> (Snd P')"
| snd2: "B >> B' ⟹ (Snd (Pair A B)) >> B'"
lemma parallel_reduction_prm:
assumes "A >> A'"
shows "(π ⋅ A) >> (π ⋅ A')"
using assms
apply induction
apply (rule parallel_reduction.refl)
apply (metis parallel_reduction.beta subst_prm trm_prm_simp(3, 4))
apply (metis parallel_reduction.eta trm_prm_simp(4))
apply (metis parallel_reduction.app trm_prm_simp(3))
apply (metis parallel_reduction.pair trm_prm_simp(5))
apply (metis parallel_reduction.fst1 trm_prm_simp(6))
apply (metis parallel_reduction.fst2 trm_prm_simp(5, 6))
apply (metis parallel_reduction.snd1 trm_prm_simp(7))
apply (metis parallel_reduction.snd2 trm_prm_simp(5, 7))
done
lemma parallel_reduction_fvs:
assumes "A >> A'"
shows "fvs A' ⊆ fvs A"
using assms proof(induction)
case (refl A)
thus ?case by auto
next
case (beta A A' B B' x T)
have *:"fvs (App (Fn x T A) B) = fvs A - {x} ∪ fvs B" using fvs_simp(3, 4) by metis
have "fvs (A'[x ::= B']) ⊆ fvs A' - {x} ∪ fvs B'" using subst_fvs.
also have "... ⊆ fvs A - {x} ∪ fvs B" using beta.IH by auto
finally show ?case using fvs_simp(3, 4) by metis
next
case (eta A A' x T)
thus ?case using fvs_simp(4) Un_Diff subset_Un_eq by metis
next
case (app A A' B B')
thus ?case using fvs_simp(3) Un_mono by metis
next
case (pair A A' B B')
thus ?case using fvs_simp(5) Un_mono by metis
next
case (fst1 P P')
thus ?case using fvs_simp(6) by force
next
case (fst2 A A' B)
thus ?case using fvs_simp(5, 6) by force
next
case (snd1 P P')
thus ?case using fvs_simp(7) by force
next
case (snd2 B B' A)
thus ?case using fvs_simp(5, 7) by force
next
qed
inductive_cases parallel_reduction_unitE': "Unit >> A"
lemma parallel_reduction_unitE:
assumes "Unit >> A"
shows "A = Unit"
using assms
apply (rule parallel_reduction_unitE'[where A=A])
apply blast
apply (auto simp add: unit_not_app unit_not_fn unit_not_pair unit_not_fst unit_not_snd)
done
inductive_cases parallel_reduction_varE': "(Var x) >> A"
lemma parallel_reduction_varE:
assumes "(Var x) >> A"
shows "A = Var x"
using assms
apply (rule parallel_reduction_varE'[where x=x and A=A])
apply blast
apply (auto simp add: var_not_app var_not_fn var_not_pair var_not_fst var_not_snd)
done
inductive_cases parallel_reduction_fnE': "(Fn x T A) >> X"
lemma parallel_reduction_fnE:
assumes "(Fn x T A) >> X"
shows "X = Fn x T A ∨ (∃A'. (A >> A') ∧ X = Fn x T A')"
using assms proof(induction rule: parallel_reduction_fnE'[where x=x and T=T and A=A and X=X])
case (4 B B' y S)
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 ?case proof(cases)
case 1
hence "x = y" "T = S" "A = B" by auto
thus ?thesis using 4 by metis
next
case 2
hence "x ≠ y" "T = S" "x ∉ fvs B" "A = [x ↔ y] ⋅ B" by auto
hence "x ∉ fvs B'" "A >> ([x ↔ y] ⋅ B')"
using parallel_reduction_fvs parallel_reduction_prm ‹B >> B'› by auto
thus ?thesis using fn_eq ‹X = Fn y S B'› ‹x ≠ y› ‹T = S› by metis
next
qed
next
qed (
metis assms,
blast,
metis app_not_fn,
metis app_not_fn,
metis fn_not_pair,
metis fn_not_fst,
metis fn_not_fst,
metis fn_not_snd,
metis fn_not_snd
)
inductive_cases parallel_reduction_redexE': "(App (Fn x T A) B) >> X"
lemma parallel_reduction_redexE:
assumes "(App (Fn x T A) B) >> X"
shows "
(X = App (Fn x T A) B) ∨
(∃A' B'. (A >> A') ∧ (B >> B') ∧ X = (A'[x ::= B'])) ∨
(∃A' B'. ((Fn x T A) >> (Fn x T A')) ∧ (B >> B') ∧ X = (App (Fn x T A') B'))
"
using assms proof(induction rule: parallel_reduction_redexE'[where x=x and T=T and A=A and B=B and X=X])
case (5 C C' D D')
from ‹App (Fn x T A) B = App C D› have C: "C = Fn x T A" and D: "D = B"
by (metis trm_simp(2), metis trm_simp(3))
from C and ‹C >> C'› obtain A' where C': "C' = Fn x T A'"
using parallel_reduction_fnE by metis
thus ?thesis using C C' D ‹C >> C'› ‹D >> D'› ‹X = App C' D'› by metis
next
case (3 C C' D D' y S)
from ‹App (Fn x T A) B = App (Fn y S C) D› have "Fn x T A = Fn y S C" and B: "B = D"
by (metis trm_simp(2), metis trm_simp(3))
from this consider
"x = y ∧ T = S ∧ A = C"
| "x ≠ y ∧ T = S ∧ A = [x ↔ y] ⋅ C ∧ x ∉ fvs C"
using trm_simp(4) by metis
thus ?case proof(cases)
case 1
thus ?thesis using ‹C >> C'› ‹X = (C'[y ::= D'])› ‹D >> D'› B by metis
next
case 2
hence "x ≠ y" "T = S" and A: "A = [x ↔ y] ⋅ C" "x ∉ fvs C" by auto
have "x ∉ fvs C'" using parallel_reduction_fvs ‹x ∉ fvs C› ‹C >> C'› by force
have "A >> ([x ↔ y] ⋅ C')"
using parallel_reduction_prm ‹C >> C'› A by metis
moreover have "X = (([x ↔ y] ⋅ C')[x ::= D'])"
using ‹X = (C'[y ::= D'])› subst_swp ‹x ∉ fvs C'› by metis
ultimately show ?thesis using ‹D >> D'› B by metis
next
qed
next
qed (
metis assms,
blast,
metis app_not_fn,
metis app_not_pair,
metis app_not_fst,
metis app_not_fst,
metis app_not_snd,
metis app_not_snd
)
inductive_cases parallel_reduction_nonredexE': "(App A B) >> X"
lemma parallel_reduction_nonredexE:
assumes "(App A B) >> X" and "⋀x T A'. A ≠ Fn x T A'"
shows "∃A' B'. (A >> A') ∧ (B >> B') ∧ X = (App A' B')"
using assms proof(induction rule: parallel_reduction_nonredexE'[where A=A and B=B and X=X])
case (5 C C' D D')
hence "A = C" "B = D" using trm_simp(2, 3) by auto
thus ?case using ‹C >> C'› ‹D >> D'› ‹X = App C' D'› by metis
next
qed (
metis assms(1),
metis parallel_reduction.refl,
metis trm_simp(2, 3) assms(2),
metis app_not_fn,
metis app_not_pair,
metis app_not_fst,
metis app_not_fst,
metis app_not_snd,
metis app_not_snd
)
inductive_cases parallel_reduction_pairE': "(Pair A B) >> X"
lemma parallel_reduction_pairE:
assumes "(Pair A B) >> X"
shows "∃A' B'. (A >> A') ∧ (B >> B') ∧ (X = Pair A' B')"
using assms proof(induction rule: parallel_reduction_pairE'[where A=A and B=B and X=X])
case 2
thus ?case using parallel_reduction.refl by blast
next
case (6 A A' B B')
thus ?case using parallel_reduction.pair trm_simp(5, 6) by fastforce
next
qed (
metis assms,
metis app_not_pair,
metis fn_not_pair,
metis app_not_pair,
metis pair_not_fst,
metis pair_not_fst,
metis pair_not_snd,
metis pair_not_snd
)
inductive_cases parallel_reduction_fstE': "(Fst P) >> X"
lemma parallel_reduction_fstE:
assumes "(Fst P) >> X"
shows "(∃P'. (P >> P') ∧ X = (Fst P')) ∨ (∃A A' B. (P = Pair A B) ∧ (A >> A') ∧ X = A')"
using assms proof(induction rule: parallel_reduction_fstE'[where P=P and X=X])
case (7 P P')
thus ?case using parallel_reduction.fst1 trm_simp(7) by metis
next
case (8 A B)
thus ?case using parallel_reduction.fst2 trm_simp(7) by metis
next
qed (
metis assms,
insert parallel_reduction.refl, metis,
metis app_not_fst,
metis fn_not_fst,
metis app_not_fst,
metis pair_not_fst,
metis fst_not_snd,
metis fst_not_snd
)
inductive_cases parallel_reduction_sndE': "(Snd P) >> X"
lemma parallel_reduction_sndE:
assumes "(Snd P) >> X"
shows "(∃P'. (P >> P') ∧ X = (Snd P')) ∨ (∃A B B'. (P = Pair A B) ∧ (B >> B') ∧ X = B')"
using assms proof(induction rule: parallel_reduction_sndE'[where P=P and X=X])
case (9 P P')
thus ?case using parallel_reduction.snd1 trm_simp(8) by metis
next
case (10 A B)
thus ?case using parallel_reduction.snd2 trm_simp(8) by metis
next
qed (
metis assms,
insert parallel_reduction.refl, metis,
metis app_not_snd,
metis fn_not_snd,
metis app_not_snd,
metis pair_not_snd,
metis fst_not_snd,
metis fst_not_snd
)
lemma parallel_reduction_subst_inner:
assumes "M >> M'"
shows "X[z ::= M] >> (X[z ::= M'])"
using assms proof(induction X rule: trm_strong_induct[where S="{z} ∪ fvs M ∪ fvs M'"])
show "finite ({z} ∪ fvs M ∪ fvs M')" using fvs_finite by auto
case 1
thus ?case using subst_simp_unit parallel_reduction.refl by metis
next
case (2 x)
thus ?case by(cases "x = z", metis subst_simp_var1, metis subst_simp_var2 parallel_reduction.refl)
next
case (3 A B)
thus ?case using subst_simp_app parallel_reduction.app by metis
next
case (4 x T A)
hence "x ≠ z" "x ∉ fvs M" "x ∉ fvs M'" by auto
thus ?case using 4 subst_simp_fn parallel_reduction.eta by metis
next
case (5 A B)
thus ?case using subst_simp_pair parallel_reduction.pair by metis
next
case (6 P)
thus ?case using subst_simp_fst parallel_reduction.fst1 by metis
next
case (7 P)
thus ?case using subst_simp_snd parallel_reduction.snd1 by metis
next
qed
lemma parallel_reduction_subst:
assumes "X >> X'" "M >> M'"
shows "X[z ::= M] >> (X'[z ::= M'])"
using assms proof(induction X arbitrary: X' rule: trm_strong_depth_induct[where S="{z} ∪ fvs M ∪ fvs M'"])
show "finite ({z} ∪ fvs M ∪ fvs M')" using fvs_finite by auto
next
case 1
hence "X' = Unit" using parallel_reduction_unitE by metis
thus ?case using parallel_reduction.refl subst_simp_unit by metis
next
case (2 x)
hence "X' = Var x" using parallel_reduction_varE by metis
thus ?case using parallel_reduction_subst_inner ‹M >> M'› by metis
next
case (3 C D)
consider "∃x T A. C = Fn x T A" | "∄x T A. C = Fn x T A" by metis
thus ?case proof(cases)
case 1
from this obtain x T A where C: "C = Fn x T A" by auto
have "depth C < depth (App C D)" "depth D < depth (App C D)"
using depth_app by auto
consider
"X' = App (Fn x T A) D"
| "∃A' D'. ((Fn x T A) >> (Fn x T A')) ∧ (D >> D') ∧ X' = (App (Fn x T A') D')"
| "∃A' D'. (A >> A') ∧ (D >> D') ∧ X' = (A'[x ::= D'])"
using parallel_reduction_redexE ‹(App C D) >> X'› C by metis
thus ?thesis proof(cases)
case 1
thus ?thesis using parallel_reduction_subst_inner ‹M >> M'› C by metis
next
case 2
from this obtain A' D'
where "(Fn x T A) >> (Fn x T A')" "D >> D'" and X': "X' = App (Fn x T A') D'"
by auto
have *: "((Fn x T A)[z ::= M]) >> ((Fn x T A')[z ::= M'])"
using "3.IH" ‹depth C < depth (App C D)› C ‹(Fn x T A) >> (Fn x T A')› ‹M >> M'›
by metis
have **: "(D[z ::= M]) >> (D'[z ::= M'])"
using "3.IH" ‹depth D < depth (App C D)› ‹D >> D'› ‹M >> M'›
by metis
have "(App C D)[z ::= M] = App ((Fn x T A)[z ::= M]) (D[z ::= M])"
using subst_simp_app C by metis
moreover have "... >> (App ((Fn x T A')[z ::= M']) (D'[z ::= M']))"
using * ** parallel_reduction.app by metis
moreover have "... = ((App (Fn x T A') D')[z ::= M'])"
using subst_simp_app by metis
moreover have "... = (X'[z ::= M'])"
using X' by metis
ultimately show ?thesis by metis
next
case 3
from this obtain A' D' where "A >> A'" "D >> D'" and X': "X' = (A'[x ::= D'])"
by auto
have "depth A < depth (App C D)"
using C depth_app depth_fn dual_order.strict_trans by fastforce
have "finite ({z} ∪ fvs M ∪ fvs M' ∪ fvs A')" using fvs_finite by auto
from this obtain y
where "y ∉ {z} ∪ fvs M ∪ fvs M' ∪ fvs A'" and C: "C = Fn y T ([y ↔ x] ⋅ A)"
using fresh_fn C by metis
hence "y ≠ z" "y ∉ fvs M" "y ∉ fvs M'" "y ∉ fvs A'" by auto
have "([y ↔ x] ⋅ A) >> ([y ↔ x] ⋅ A')" using parallel_reduction_prm ‹A >> A'› by metis
hence *: "([y ↔ x] ⋅ A)[z ::= M] >> (([y ↔ x] ⋅ A')[z ::= M'])"
using "3.IH" ‹depth A < depth (App C D)› depth_prm
using ‹([y ↔ x] ⋅ A) >> ([y ↔ x] ⋅A')› ‹M >> M'› by metis
have **: "(D[z ::= M]) >> (D'[z ::= M'])"
using "3.IH" ‹depth D < depth (App C D)› ‹D >> D'› ‹M >> M'›
by metis
have "(App C D)[z ::= M] = (App ((Fn y T ([y ↔ x] ⋅ A))[z ::= M]) (D[z ::= M]))"
using C subst_simp_app by metis
moreover have "... = (App (Fn y T (([y ↔ x] ⋅ A)[z ::= M])) (D[z ::= M]))"
using ‹y ≠ z› ‹y ∉ fvs M› subst_simp_fn by metis
moreover have "... >> (([y ↔ x] ⋅ A')[z ::= M'][y ::= D'[z ::= M']])"
using parallel_reduction.beta * ** by metis
moreover have "... = (([y ↔ x] ⋅ A')[y ::= D'][z ::= M'])"
using barendregt ‹y ≠ z› ‹y ∉ fvs M'› by metis
moreover have "... = (A'[x ::= D'][z ::= M'])"
using subst_swp ‹y ∉ fvs A'› by metis
moreover have "... = (X'[z ::= M'])" using X' by metis
ultimately show ?thesis by metis
next
qed
next
case 2
from this obtain C' D' where "C >> C'" "D >> D'" and X': "X' = App C' D'"
using parallel_reduction_nonredexE ‹(App C D) >> X'› by metis
have "depth C < depth (App C D)" "depth D < depth (App C D)"
using depth_app by auto
hence *: "(C[z ::= M]) >> (C'[z ::= M'])" and **: "(D[z ::= M]) >> (D'[z ::= M'])"
using "3.IH" ‹C >> C'› ‹D >> D'› ‹M >> M'› by metis+
have "(App C D)[z ::= M] = App (C[z ::= M]) (D[z ::= M])"
using subst_simp_app by metis
moreover have "... >> (App (C'[z ::= M']) (D'[z ::= M']))"
using parallel_reduction.app * ** by metis
moreover have "... = ((App C' D')[z ::= M'])"
using subst_simp_app by metis
moreover have "... = (X'[z ::= M'])" using X' by metis
ultimately show ?thesis by metis
next
qed
next
case (4 x T A)
hence "x ≠ z" "x ∉ fvs M" "x ∉ fvs M'"
by auto
from ‹(Fn x T A) >> X'› consider
"X' = Fn x T A"
| "∃A'. (A >> A') ∧ X' = Fn x T A'" using parallel_reduction_fnE by metis
thus ?case proof(cases)
case 1
thus ?thesis using parallel_reduction_subst_inner ‹M >> M'› by metis
next
case 2
from this obtain A' where "A >> A'" and X': "X' = Fn x T A'" by auto
hence *: "(A[z ::= M]) >> (A'[z ::= M'])"
using "4.IH" depth_fn ‹A >> A'› ‹M >> M'› by metis
have "((Fn x T A)[z ::= M]) = (Fn x T (A[z ::= M]))"
using subst_simp_fn ‹x ≠ z› ‹x ∉ fvs M› by metis
moreover have "... >> (Fn x T (A'[z ::= M']))"
using parallel_reduction.eta * by metis
moreover have "... = ((Fn x T A')[z ::= M'])"
using subst_simp_fn ‹x ≠ z› ‹x ∉ fvs M'› by metis
moreover have "... = (X'[z ::= M'])"
using X' by metis
ultimately show ?thesis by metis
next
qed
next
case (5 A B)
from ‹(Pair A B) >> X'› consider
"X' = Pair A B"
| "∃A' B'. (A >> A') ∧ (B >> B') ∧ X' = Pair A' B'"
using parallel_reduction_pairE by metis
thus ?case proof(cases)
case 1
thus ?thesis using parallel_reduction_subst_inner ‹M >> M'› by metis
next
case 2
from this obtain A' B' where "A >> A'" "B >> B'" and X': "X' = Pair A' B'" by auto
have *: "(A[z ::= M]) >> (A'[z ::= M'])" and **: "(B[z ::= M]) >> (B'[z ::= M'])"
using "5.IH" ‹A >> A'› ‹B >> B'› ‹M >> M'› by (metis depth_pair(1), metis depth_pair(2))
have "(Pair A B)[z ::= M] = (Pair (A[z ::= M]) (B[z ::= M]))"
using subst_simp_pair by metis
moreover have "... >> (Pair (A'[z ::= M']) (B'[z ::= M']))"
using parallel_reduction.pair * ** by metis
moreover have "... = ((Pair A' B')[z ::= M'])"
using subst_simp_pair by metis
moreover have "... = (X'[z ::= M'])" using X' by metis
ultimately show ?thesis by metis
next
qed
next
case (6 P)
from ‹(Fst P) >> X'› consider
"∃P'. (P >> P') ∧ X' = Fst P'"
| "∃A A' B. P = Pair A B ∧ (A >> A') ∧ X' = A'"
using parallel_reduction_fstE by metis
thus ?case proof(cases)
case 1
from this obtain P' where "P >> P'" and X': "X' = Fst P'" by auto
have *: "(P[z ::= M]) >> (P'[z ::= M'])"
using "6.IH" depth_fst ‹P >> P'› ‹M >> M'› by metis
have "(Fst P)[z ::= M] = Fst (P[z ::= M])"
using subst_simp_fst by metis
moreover have "... >> (Fst (P'[z ::= M']))"
using parallel_reduction.fst1 * by metis
moreover have "... = ((Fst P')[z ::= M'])"
using subst_simp_fst by metis
moreover have "... = (X'[z ::= M'])" using X' by metis
ultimately show ?thesis by metis
next
case 2
from this obtain A A' B where P: "P = Pair A B" "A >> A'" and X': "X' = A'" by auto
have "depth A < depth (Fst P)"
using P depth_fst depth_pair dual_order.strict_trans by fastforce
hence *: "(A[z ::= M]) >> (A'[z ::= M'])"
using "6.IH" ‹A >> A'› ‹M >> M'› by metis
have "(Fst P)[z ::= M] = (Fst (Pair (A[z ::= M]) (B[z ::= M])))"
using P subst_simp_fst subst_simp_pair by metis
moreover have "... >> (A'[z ::= M'])"
using parallel_reduction.fst2 * by metis
moreover have "... = (X'[z ::= M'])"
using X' by metis
ultimately show ?thesis by metis
next
qed
next
case (7 P)
from ‹(Snd P) >> X'› consider
"∃P'. (P >> P') ∧ X' = Snd P'"
| "∃A B B'. P = Pair A B ∧ (B >> B') ∧ X' = B'"
using parallel_reduction_sndE by metis
thus ?case proof(cases)
case 1
from this obtain P' where "P >> P'" and X': "X' = Snd P'" by auto
have *: "(P[z ::= M]) >> (P'[z ::= M'])"
using "7.IH" depth_snd ‹P >> P'› ‹M >> M'› by metis
have "(Snd P)[z ::= M] = Snd (P[z ::= M])"
using subst_simp_snd by metis
moreover have "... >> (Snd (P'[z ::= M']))"
using parallel_reduction.snd1 * by metis
moreover have "... = ((Snd P')[z ::= M'])"
using subst_simp_snd by metis
moreover have "... = (X'[z ::= M'])" using X' by metis
ultimately show ?thesis by metis
next
case 2
from this obtain A B B' where P: "P = Pair A B" "B >> B'" and X': "X' = B'" by auto
have "depth B < depth (Snd P)"
using P depth_snd depth_pair dual_order.strict_trans by fastforce
hence *: "(B[z ::= M]) >> (B'[z ::= M'])"
using "7.IH" ‹B >> B'› ‹M >> M'› by metis
have "(Snd P)[z ::= M] = (Snd (Pair (A[z ::= M]) (B[z ::= M])))"
using P subst_simp_snd subst_simp_pair by metis
moreover have "... >> (B'[z ::= M'])"
using parallel_reduction.snd2 * by metis
moreover have "... = (X'[z ::= M'])"
using X' by metis
ultimately show ?thesis by metis
next
qed
next
qed
inductive complete_development :: "'a trm ⇒ 'a trm ⇒ bool" ("_ >>> _") where
unit: "Unit >>> Unit"
| var: "(Var x) >>> (Var x)"
| beta: "⟦A >>> A'; B >>> B'⟧ ⟹ (App (Fn x T A) B) >>> (A'[x ::= B'])"
| eta: "A >>> A' ⟹ (Fn x T A) >>> (Fn x T A')"
| app: "⟦A >>> A'; B >>> B'; (⋀x T M. A ≠ Fn x T M)⟧ ⟹ (App A B) >>> (App A' B')"
| pair: "⟦A >>> A'; B >>> B'⟧ ⟹ (Pair A B) >>> (Pair A' B')"
| fst1: "⟦P >>> P'; (⋀A B. P ≠ Pair A B)⟧ ⟹ (Fst P) >>> (Fst P')"
| fst2: "A >>> A' ⟹ (Fst (Pair A B)) >>> A'"
| snd1: "⟦P >>> P'; (⋀A B. P ≠ Pair A B)⟧ ⟹ (Snd P) >>> (Snd P')"
| snd2: "B >>> B' ⟹ (Snd (Pair A B)) >>> B'"
lemma not_fn_prm:
assumes "⋀x T M. A ≠ Fn x T M"
shows "π ⋅ A ≠ Fn x T M"
proof(rule classical)
fix x T M
obtain π' where *: "π' = prm_inv π" by auto
assume "¬(π ⋅ A ≠ Fn x T M)"
hence "π ⋅ A = Fn x T M" by blast
hence "π' ⋅ (π ⋅ A) = π' ⋅ Fn x T M" by fastforce
hence "(π' ⋄ π) ⋅ A = π' ⋅ Fn x T M"
using trm_prm_apply_compose by metis
hence "A = π' ⋅ Fn x T M"
using * prm_inv_compose trm_prm_apply_id by metis
hence "A = Fn (π' $ x) T (π' ⋅ M)" using trm_prm_simp(4) by metis
hence False using assms by blast
thus ?thesis by blast
qed
lemma not_pair_prm:
assumes "⋀A B. P ≠ Pair A B"
shows "π ⋅ P ≠ Pair A B"
proof(rule classical)
fix A B
obtain π' where *: "π' = prm_inv π" by auto
assume "¬(π ⋅ P ≠ Pair A B)"
hence "π ⋅ P = Pair A B" by blast
hence "π' ⋅ π ⋅ P = π' ⋅ (Pair A B)" by fastforce
hence "(π' ⋄ π) ⋅ P = π' ⋅ (Pair A B)"
using trm_prm_apply_compose by metis
hence "P = π' ⋅ (Pair A B)"
using * prm_inv_compose trm_prm_apply_id by metis
hence "P = Pair (π' ⋅ A) (π' ⋅ B)" using trm_prm_simp(5) by metis
hence False using assms by blast
thus ?thesis by blast
qed
lemma complete_development_prm:
assumes "A >>> A'"
shows "(π ⋅ A) >>> (π ⋅ A')"
using assms proof(induction)
case unit
thus ?case using complete_development.unit trm_prm_simp(1) by metis
next
case (var x)
thus ?case using complete_development.var trm_prm_simp(2) by metis
next
case (beta A A' B B' x T)
thus ?case using complete_development.beta subst_prm trm_prm_simp(3, 4) by metis
next
case (eta A A' x T)
thus ?case using complete_development.eta trm_prm_simp(4) by metis
next
case (app A A' B B')
thus ?case using complete_development.app by (simp add: trm_prm_simp(3) not_fn_prm)
next
case (pair A A' B B')
thus ?case using complete_development.pair trm_prm_simp(5) by metis
next
case (fst1 P P')
hence "π ⋅ P ≠ Pair A B" for A B using not_pair_prm by metis
thus ?case using trm_prm_simp(6) fst1.IH complete_development.fst1 by metis
next
case (fst2 A A' B)
thus ?case using trm_prm_simp(5, 6) complete_development.fst2 by metis
next
case (snd1 P P')
hence "π ⋅ P ≠ Pair A B" for A B using not_pair_prm by metis
thus ?case using trm_prm_simp(7) snd1.IH complete_development.snd1 by metis
next
case (snd2 B B' A)
thus ?case using trm_prm_simp(5, 7) complete_development.snd2 by metis
next
qed
lemma complete_development_fvs:
assumes "A >>> A'"
shows "fvs A' ⊆ fvs A"
using assms proof(induction)
case unit
thus ?case using fvs_simp by auto
next
case (var x)
thus ?case using fvs_simp by auto
next
case (beta A A' B B' x T)
have "fvs (A'[x ::= B']) ⊆ fvs A' - {x} ∪ fvs B'" using subst_fvs.
also have "... ⊆ fvs A - {x} ∪ fvs B" using beta.IH by auto
also have "... ⊆ fvs (Fn x T A) ∪ fvs B" using fvs_simp(4) subset_refl by force
also have "... ⊆ fvs (App (Fn x T A) B)" using fvs_simp(3) subset_refl by force
finally show ?case.
next
case (eta A A' x T)
thus ?case using fvs_simp(4) using Un_Diff subset_Un_eq by (metis (no_types, lifting))
next
case (app A A' B B')
thus ?case using fvs_simp(3) Un_mono by metis
next
case (pair A A' B B')
thus ?case using fvs_simp(5) Un_mono by metis
next
case (fst1 P P')
thus ?case using fvs_simp(6) by force
next
case (fst2 A A' B)
thus ?case by (simp add: fvs_simp(5, 6) sup.coboundedI1)
next
case (snd1 P P')
thus ?case using fvs_simp(7) by fastforce
next
case (snd2 B B' A)
thus ?case using fvs_simp(5, 7) by fastforce
next
qed
lemma complete_development_fnE:
assumes "(Fn x T A) >>> X"
shows "∃A'. (A >>> A') ∧ X = Fn x T A'"
using assms proof(cases)
case (eta B B' y S)
hence "T = S" using trm_simp(4) by metis
from eta consider "x = y ∧ A = B" | "x ≠ y ∧ x ∉ fvs B ∧ A = [x ↔ y] ⋅ B"
using trm_simp(4) by metis
thus ?thesis proof(cases)
case 1
hence "x = y" and "A = B" by auto
obtain A' where "A' = B'" by auto
hence "A >>> A'" and "X = Fn x T A'" using eta ‹A = B› ‹x = y› ‹T = S› by auto
thus ?thesis by auto
next
case 2
hence "x ≠ y" "x ∉ fvs B" and A: "A = [x ↔ y] ⋅ B" by auto
hence "x ∉ fvs B'" using ‹B >>> B'› complete_development_fvs by auto
obtain A' where A': "A' = [x ↔ y] ⋅ B'" by auto
hence "A >>> A'" using A ‹B >>> B'› complete_development_prm by auto
have "X = Fn x T A'"
using fn_eq ‹x ≠ y› ‹x ∉ fvs B'› A' ‹X = Fn y S B'› ‹T = S› by metis
thus ?thesis using ‹A >>> A'› by auto
next
qed
next
qed (
metis unit_not_fn,
metis var_not_fn,
metis app_not_fn,
metis app_not_fn,
metis fn_not_pair,
metis fn_not_fst,
metis fn_not_fst,
metis fn_not_snd,
metis fn_not_snd
)
lemma complete_development_pairE:
assumes "(Pair A B) >>> X"
shows "∃A' B'. (A >>> A') ∧ (B >>> B') ∧ X = Pair A' B'"
using assms
apply cases
apply (metis unit_not_pair, metis var_not_pair, metis app_not_pair, metis fn_not_pair, metis app_not_pair)
apply (metis trm_simp(5, 6))
apply (metis pair_not_fst, metis pair_not_fst, metis pair_not_snd, metis pair_not_snd)
done
lemma complete_development_exists:
shows "∃X. (A >>> X)"
proof(induction A rule: trm_induct)
case 1
obtain X :: "'a trm" where "X = Unit" by auto
hence "Unit >>> X" using complete_development.unit by metis
thus ?case by auto
next
case (2 x)
obtain X where "X = Var x" by auto
hence "(Var x) >>> X" using complete_development.var by metis
thus ?case by auto
next
case (3 A B)
from this obtain A' B' where A': "A >>> A'" and B': "B >>> B'" by auto
consider "(∃x T M. A = Fn x T M)" | "¬(∃x T M. A = Fn x T M)" by auto
thus ?case proof(cases)
case 1
from this obtain x T M where A: "A = Fn x T M" by auto
from this obtain M' where "A' = Fn x T M'" and "M >>> M'"
using complete_development_fnE A' by metis
obtain X where "X = (M'[x ::= B'])" by auto
hence "(App A B) >>> X"
using complete_development.beta ‹M >>> M'› B' A by metis
thus ?thesis by auto
next
case 2
thus ?thesis using complete_development.app A' B' by metis
next
qed
next
case (4 x T A)
from this obtain A' where A': "A >>> A'" by auto
obtain X where "X = Fn x T A'" by auto
hence "(Fn x T A) >>> X" using complete_development.eta A' by metis
thus ?case by auto
next
case (5 A B)
thus ?case using complete_development.pair by blast
next
case (6 P)
consider "∃A B. P = Pair A B" | "∄A B. P = Pair A B" by auto
thus ?case proof(cases)
case 1
from this obtain A B X where "P = Pair A B" "P >>> X" using 6 by auto
from this obtain A' B' where "A >>> A'" "B >>> B'" "X = Pair A' B'"
using complete_development_pairE by metis
thus ?thesis using complete_development.fst2 ‹P = Pair A B› by metis
next
case 2
thus ?thesis using complete_development.fst1 6 by blast
next
qed
next
case (7 P)
consider "∃A B. P = Pair A B" | "∄A B. P = Pair A B" by auto
thus ?case proof(cases)
case 1
from this obtain A B X where "P = Pair A B" "P >>> X" using 7 by auto
from this obtain A' B' where "A >>> A'" "B >>> B'" "X = Pair A' B'"
using complete_development_pairE by metis
thus ?thesis using complete_development.snd2 ‹P = Pair A B› by metis
next
case 2
thus ?thesis using complete_development.snd1 7 by blast
next
qed
next
qed
lemma complete_development_triangle:
assumes "A >>> D" "A >> B"
shows "B >> D"
using assms proof(induction arbitrary: B rule: complete_development.induct)
case unit
thus ?case using parallel_reduction_unitE parallel_reduction.refl by metis
next
case (var x)
thus ?case using parallel_reduction_varE parallel_reduction.refl by metis
next
case (beta A A' C C' x T)
hence "A >> A'" "C >> C'" using parallel_reduction.refl by metis+
from ‹(App (Fn x T A) C) >> B› consider
"B = App (Fn x T A) C"
| "∃A'' C''. (A >> A'') ∧ (C >> C'') ∧ B = (A''[x ::= C''])"
| "∃A'' C''. ((Fn x T A) >> (Fn x T A'')) ∧ (C >> C'') ∧ B = (App (Fn x T A'') C'')"
using parallel_reduction_redexE by metis
thus ?case proof(cases)
case 1
thus ?thesis using parallel_reduction.beta ‹A >> A'› ‹C >> C'› by metis
next
case 2
from this obtain A'' C'' where "A >> A''" "C >> C''" and B: "B = (A''[x ::= C''])" by auto
hence "A'' >> A'" "C'' >> C'" using beta.IH by metis+
thus ?thesis using B parallel_reduction_subst by metis
next
case 3
from this obtain A'' C''
where "(Fn x T A) >> (Fn x T A'')" "C >> C''" and B: "B = App (Fn x T A'') C''"
by auto
hence "C'' >> C'" using beta.IH by metis
have "A'' >> A'"
proof -
thm parallel_reduction_fnE
from ‹(Fn x T A) >> (Fn x T A'')› consider
"Fn x T A = Fn x T A''"
| "∃A'''. (A >> A''') ∧ Fn x T A'' = Fn x T A'''"
using parallel_reduction_fnE by metis
hence "A >> A''" proof(cases)
case 1
hence "A = A''" using trm_simp(4) by metis
thus ?thesis using parallel_reduction.refl by metis
next
case 2
from this obtain A''' where "A >> A'''" "Fn x T A'' = Fn x T A'''" by auto
thus ?thesis using trm_simp(4) by metis
next
qed
thus ?thesis using beta.IH by metis
qed
thus ?thesis using B ‹C'' >> C'› parallel_reduction.beta by metis
next
qed
next
case (eta A A' x T B)
from this consider
"B = Fn x T A"
| "∃A''. (A >> A'') ∧ B = Fn x T A''" using parallel_reduction_fnE by metis
thus ?case proof(cases)
case 1
thus ?thesis using eta.IH parallel_reduction.refl parallel_reduction.eta by metis
next
case 2
from this obtain A'' where "A >> A''" and "B = Fn x T A''" by auto
thus ?thesis using eta.IH parallel_reduction.eta by metis
next
qed
next
case (app A A' C C')
from this obtain A'' C'' where "A >> A''" "C >> C''" and B: "B = App A'' C''"
using parallel_reduction_nonredexE by metis
hence "A'' >> A'" "C'' >> C'" using app.IH by metis+
thus ?case using B parallel_reduction.app by metis
next
case (pair A A' C C')
from ‹(Pair A C) >> B› and parallel_reduction_pairE obtain A'' C'' where
"A >> A''" "C >> C''" "B = Pair A'' C''" by metis
thus ?case using pair.IH parallel_reduction.pair by metis
next
case (fst1 P P')
from this obtain P'' where "P >> P''" "B = Fst P''"
using parallel_reduction_fstE by blast
thus ?case using fst1.IH parallel_reduction.fst1 by metis
next
case (fst2 A A' C B)
from this consider
"∃P''. ((Pair A C) >> P'') ∧ B = Fst P''"
| "∃A''. (A >> A'') ∧ (B = A'')"
using parallel_reduction_fstE[where P="(Pair A C)" and X=B] using trm_simp(5) by metis
thus ?case proof(cases)
case 1
from this obtain P'' where "(Pair A C) >> P''" and "B = Fst P''" by auto
from this obtain A'' C'' where "P'' = Pair A'' C''" "A >> A''" "C >> C''"
using parallel_reduction_pairE by metis
thus ?thesis using fst2 parallel_reduction.fst2 ‹B = Fst P''› by metis
next
case 2
from this obtain A'' where "A >> A''" "B = A''" by metis
thus ?thesis using fst2 by metis
next
qed
next
case (snd1 P P')
from this obtain P'' where "P >> P''" "B = Snd P''"
using parallel_reduction_sndE by blast
thus ?case using snd1.IH parallel_reduction.snd1 by metis
next
case (snd2 C A' A B)
from this consider
"∃P''. ((Pair A C) >> P'') ∧ B = Snd P''"
| "∃C''. (C >> C'') ∧ (B = C'')"
using parallel_reduction_sndE[where P="(Pair A C)" and X=B] using trm_simp(5, 6) by metis
thus ?case proof(cases)
case 1
from this obtain P'' where "(Pair A C) >> P''" and "B = Snd P''" by auto
from this obtain A'' C'' where "P'' = Pair A'' C''" "A >> A''" "C >> C''"
using parallel_reduction_pairE by metis
thus ?thesis using snd2 parallel_reduction.snd2 ‹B = Snd P''› by metis
next
case 2
from this obtain C'' where "C >> C''" "B = C''" by metis
thus ?thesis using snd2 by metis
next
qed
next
qed
lemma parallel_reduction_diamond:
assumes "A >> B" "A >> C"
shows "∃D. (B >> D) ∧ (C >> D)"
proof -
obtain D where "A >>> D" using complete_development_exists by metis
hence "(B >> D) ∧ (C >> D)" using complete_development_triangle assms by auto
thus ?thesis by blast
qed
inductive parallel_reduces :: "'a trm ⇒ 'a trm ⇒ bool" ("_ >>⇧* _") where
reflexive: "A >>⇧* A"
| transitive: "⟦A >>⇧* A'; A' >> A''⟧ ⟹ A >>⇧* A''"
lemma parallel_reduces_diamond':
assumes "A >>⇧* C" "A >> B"
shows "∃D. (B >>⇧* D) ∧ (C >> D)"
using assms proof(induction)
case (reflexive A)
thus ?case using parallel_reduces.reflexive by metis
next
case (transitive A A' A'')
from this obtain C where "B >>⇧* C" "A' >> C" by metis
from ‹A' >> C› ‹A' >> A''› obtain D where "C >> D" "A'' >> D"
using parallel_reduction_diamond by metis
thus ?case using parallel_reduces.transitive ‹B >>⇧* C› by metis
next
qed
lemma parallel_reduces_diamond:
assumes "A >>⇧* B" "A >>⇧* C"
shows "∃D. (B >>⇧* D) ∧ (C >>⇧* D)"
using assms proof(induction)
case (reflexive A)
thus ?case using parallel_reduces.reflexive by metis
next
case (transitive A A' A'')
from this obtain C' where "A' >>⇧* C'" "C >>⇧* C'" by metis
from this obtain D where "A'' >>⇧* D" "C' >> D"
using ‹A' >> A''› ‹A' >>⇧* C'› parallel_reduces_diamond' by metis
thus ?case using parallel_reduces.transitive ‹C >>⇧* C'› by metis
next
qed
lemma beta_reduction_is_parallel_reduction:
assumes "A →β B"
shows "A >> B"
using assms
apply induction
apply (metis parallel_reduction.beta parallel_reduction.refl)
apply (metis parallel_reduction.app parallel_reduction.refl)
apply (metis parallel_reduction.app parallel_reduction.refl)
apply (metis parallel_reduction.eta)
apply (metis parallel_reduction.pair parallel_reduction.refl)
apply (metis parallel_reduction.pair parallel_reduction.refl)
apply (metis parallel_reduction.fst1)
apply (metis parallel_reduction.fst2 parallel_reduction.refl)
apply (metis parallel_reduction.snd1)
apply (metis parallel_reduction.snd2 parallel_reduction.refl)
done
lemma parallel_reduction_is_beta_reduction:
assumes "A >> B"
shows "A →β⇧* B"
using assms proof(induction)
case (refl A)
thus ?case using beta_reduces.reflexive.
next
case (beta A A' B B' x T)
hence "(App (Fn x T A) B) →β⇧* (App (Fn x T A') B')"
using ‹A →β⇧* A'›
beta_reduces_fn beta_reduces_app_left beta_reduces_app_right beta_reduces_composition
by metis
moreover have "(App (Fn x T A') B') →β (A'[x ::= B'])"
using beta_reduction.beta.
ultimately show ?case using beta_reduces.transitive by metis
next
case (eta A A' x T)
thus ?case using beta_reduces_fn by metis
next
case (app A A' B B')
thus ?case using beta_reduces_app_left beta_reduces_app_right beta_reduces_composition by metis
next
case (pair A A' B B')
thus ?case using beta_reduces_pair_left beta_reduces_pair_right beta_reduces_composition by metis
next
case (fst1 P P')
thus ?case using beta_reduces_fst by metis
next
case (fst2 A A' B)
thus ?case
using beta_reduces_pair_left beta_reduction.fst2 beta_reduces.intros beta_reduces_composition
by blast
next
case (snd1 P P')
thus ?case using beta_reduces_snd by metis
next
case (snd2 B B' A)
thus ?case
using beta_reduces_pair_left beta_reduction.snd2 beta_reduces.intros beta_reduces_composition
by blast
next
qed
lemma parallel_beta_reduces_equivalent:
shows "(A >>⇧* B) = (A →β⇧* B)"
proof -
have →: "(A >>⇧* B) ⟹ (A →β⇧* B)"
proof(induction rule: parallel_reduces.induct)
case (reflexive A)
thus ?case using beta_reduces.reflexive.
next
case (transitive A A' A'')
thus ?case using beta_reduces_composition parallel_reduction_is_beta_reduction by metis
next
qed
have ←: "(A →β⇧* B) ⟹ (A >>⇧* B)"
proof(induction rule: beta_reduces.induct)
case (reflexive A)
thus ?case using parallel_reduces.reflexive.
next
case (transitive A A' A'')
thus ?case using parallel_reduces.transitive beta_reduction_is_parallel_reduction by metis
next
qed
from ←→ show "(A >>⇧* B) = (A →β⇧* B)" by blast
qed
theorem confluence:
assumes "A →β⇧* B" "A →β⇧* C"
shows "∃D. (B →β⇧* D) ∧ (C →β⇧* D)"
proof -
from assms have "A >>⇧* B" "A >>⇧* C" using parallel_beta_reduces_equivalent by metis+
hence "∃D. (B >>⇧* D) ∧ (C >>⇧* D)" using parallel_reduces_diamond by metis
thus "∃D. (B →β⇧* D) ∧ (C →β⇧* D)" using parallel_beta_reduces_equivalent by metis
qed
end
end