(* *) (* Formalisation of some typical SOS-proofs. *) (* *) (* This work was inspired by challenge suggested by Adam *) (* Chlipala on the POPLmark mailing list. *) (* *) (* We thank Nick Benton for helping us with the *) (* termination-proof for evaluation. *) (* *) (* The formalisation was done by Julien Narboux and *) (* Christian Urban. *)
theory SOS imports"HOL-Nominal.Nominal" begin
atom_decl name
text‹types and terms› nominal_datatype ty =
TVar "nat"
| Arrow "ty""ty" (‹_→_› [100,100] 100)
lemma fresh_ty: fixes x::"name" and T::"ty" shows"x♯T" by (induct T rule: ty.induct)
(auto simp add: fresh_nat)
text‹Parallel and single substitution.› fun
lookup :: "(name×trm) list ==> name ==> trm" where "lookup [] x = Var x"
| "lookup ((y,e)#θ) x = (if x=y then e else lookup θ x)"
lemma psubst_eqvt[eqvt]: fixes pi::"name prm" and t::"trm" shows"pi∙(θ) = (pi∙θ)<(pi∙t)>" by (nominal_induct t avoiding: θ rule: trm.strong_induct)
(perm_simp add: fresh_bij lookup_eqvt)+
lemma fresh_psubst: fixes z::"name" and t::"trm" assumes"z♯t"and"z♯θ" shows"z♯(θ)" using assms by (nominal_induct t avoiding: z θ t rule: trm.strong_induct)
(auto simp add: abs_fresh lookup_fresh)
lemma psubst_empty[simp]: shows"[] = t" by (nominal_induct t rule: trm.strong_induct)
(auto simp add: fresh_list_nil)
text‹Single substitution› abbreviation
subst :: "trm ==> name ==> trm ==> trm" (‹_[_::=_]› [100,100,100] 100) where "t[x::=t'] ≡ ([(x,t')])"
lemma fresh_subst: fixes z::"name" shows"[z♯s; (z=y ∨ z♯t)]==> z♯t[y::=s]" by (nominal_induct t avoiding: z y s rule: trm.strong_induct)
(auto simp add: abs_fresh fresh_prod fresh_atm)
lemma forget: assumes a: "x♯e" shows"e[x::=e'] = e" using a by (nominal_induct e avoiding: x e' rule: trm.strong_induct)
(auto simp add: fresh_atm abs_fresh)
lemma psubst_subst_psubst: assumes h: "x♯θ" shows"θ[x::=e'] = ((x,e')#θ)" using h by (nominal_induct e avoiding: θ x e' rule: trm.strong_induct)
(auto simp add: fresh_list_cons fresh_atm forget lookup_fresh lookup_fresh')
text‹Typing Judgements›
inductive
valid :: "(name×ty) list ==> bool" where
v_nil[intro]: "valid []"
| v_cons[intro]: "[valid Γ;x♯Γ]==> valid ((x,T)#Γ)"
lemma t_Lam_elim: assumes a: "Γ ⊨ Lam [x].t : T""x♯Γ" obtains T🪙1 and T🪙2 where"(x,T🪙1)#Γ ⊨ t : T🪙2"and"T=T🪙1→T🪙2" using a by (cases rule: typing.strong_cases [where x="x"])
(auto simp add: abs_fresh fresh_ty alpha trm.inject)
abbreviation "sub_context" :: "(name×ty) list ==> (name×ty) list ==> bool" (‹_ ⊆ _› [55,55] 55) where "Γ🪙1 ⊆ Γ🪙2 ≡∀x T. (x,T)∈set Γ🪙1 ⟶ (x,T)∈set Γ🪙2"
lemma weakening: fixes Γ🪙1 Γ🪙2::"(name×ty) list" assumes"Γ🪙1 ⊨ e: T"and"valid Γ🪙2"and"Γ🪙1 ⊆ Γ🪙2" shows"Γ🪙2 ⊨ e: T" using assms proof(nominal_induct Γ🪙1 e T avoiding: Γ🪙2 rule: typing.strong_induct) case (t_Lam x Γ🪙1 T🪙1 t T🪙2 Γ🪙2) have vc: "x♯Γ🪙2"by fact have ih: "[valid ((x,T🪙1)#Γ🪙2); (x,T🪙1)#Γ🪙1 ⊆ (x,T🪙1)#Γ🪙2]==> (x,T🪙1)#Γ🪙2 ⊨ t : T🪙2"by fact have"valid Γ🪙2"by fact thenhave"valid ((x,T🪙1)#Γ🪙2)"using vc by auto moreover have"Γ🪙1 ⊆ Γ🪙2"by fact thenhave"(x,T🪙1)#Γ🪙1 ⊆ (x,T🪙1)#Γ🪙2"by simp ultimatelyhave"(x,T🪙1)#Γ🪙2 ⊨ t : T🪙2"using ih by simp with vc show"Γ🪙2 ⊨ Lam [x].t : T🪙1→T🪙2"by auto qed (auto)
lemma type_substitutivity_aux: assumes a: "(Δ@[(x,T')]@Γ) ⊨ e : T" and b: "Γ ⊨ e' : T'" shows"(Δ@Γ) ⊨ e[x::=e'] : T" using a b proof (nominal_induct Γ≡"Δ@[(x,T')]@Γ" e T avoiding: e' Δ rule: typing.strong_induct) case (t_Var y T e' Δ) thenhave a1: "valid (Δ@[(x,T')]@Γ)" and a2: "(y,T) ∈ set (Δ@[(x,T')]@Γ)" and a3: "Γ ⊨ e' : T'" . from a1 have a4: "valid (Δ@Γ)"by (rule valid_insert)
{ assume eq: "x=y" from a1 a2 have"T=T'"using eq by (auto intro: context_unique) with a3 have"Δ@Γ ⊨ Var y[x::=e'] : T"using eq a4 by (auto intro: weakening)
} moreover
{ assume ineq: "x≠y" from a2 have"(y,T) ∈ set (Δ@Γ)"using ineq by simp thenhave"Δ@Γ ⊨ Var y[x::=e'] : T"using ineq a4 by auto
} ultimatelyshow"Δ@Γ ⊨ Var y[x::=e'] : T"by blast qed (force simp add: fresh_list_append fresh_list_cons)+
corollary type_substitutivity: assumes a: "(x,T')#Γ ⊨ e : T" and b: "Γ ⊨ e' : T'" shows"Γ ⊨ e[x::=e'] : T" using a b type_substitutivity_aux[where Δ="[]"] by (auto)
text‹Values› inductive
val :: "trm==>bool" where
v_Lam[intro]: "val (Lam [x].e)"
equivariance val
lemma not_val_App[simp]: shows "¬ val (App e🪙1 e🪙2)" "¬ val (Var x)" by (auto elim: val.cases)
nominal_inductive big by (simp_all add: abs_fresh)
lemma big_preserves_fresh: fixes x::"name" assumes a: "e ⇓ e'""x♯e" shows"x♯e'" using a by (induct) (auto simp add: abs_fresh fresh_subst)
lemma b_App_elim: assumes a: "App e🪙1 e🪙2 ⇓ e'""x♯(e🪙1,e🪙2,e')" obtains f🪙1 and f🪙2 where"e🪙1 ⇓ Lam [x]. f🪙1""e🪙2 ⇓ f🪙2""f🪙1[x::=f🪙2] ⇓ e'" using a by (cases rule: big.strong_cases[where x="x"and xa="x"])
(auto simp add: trm.inject)
lemma subject_reduction: assumes a: "e ⇓ e'"and b: "Γ ⊨ e : T" shows"Γ ⊨ e' : T" using a b proof (nominal_induct avoiding: Γ arbitrary: T rule: big.strong_induct) case (b_App x e🪙1 e🪙2 e' e e🪙2' Γ T) have vc: "x♯Γ"by fact have"Γ ⊨ App e🪙1 e🪙2 : T"by fact thenobtain T' where a1: "Γ ⊨ e🪙1 : T'→T"and a2: "Γ ⊨ e🪙2 : T'" by (cases) (auto simp add: trm.inject) have ih1: "Γ ⊨ e🪙1 : T' → T ==> Γ ⊨ Lam [x].e : T' → T"by fact have ih2: "Γ ⊨ e🪙2 : T' ==> Γ ⊨ e🪙2' : T'"by fact have ih3: "Γ ⊨ e[x::=e🪙2'] : T ==> Γ ⊨ e' : T"by fact have"Γ ⊨ Lam [x].e : T'→T"using ih1 a1 by simp thenhave"((x,T')#Γ) ⊨ e : T"using vc by (auto elim: t_Lam_elim simp add: ty.inject) moreover have"Γ ⊨ e🪙2': T'"using ih2 a2 by simp ultimatelyhave"Γ ⊨ e[x::=e🪙2'] : T"by (simp add: type_substitutivity) thus"Γ ⊨ e' : T"using ih3 by simp qed (blast)
lemma subject_reduction2: assumes a: "e ⇓ e'"and b: "Γ ⊨ e : T" shows"Γ ⊨ e' : T" using a b by (nominal_induct avoiding: Γ T rule: big.strong_induct)
(force elim: t_App_elim t_Lam_elim simp add: ty.inject type_substitutivity)+
lemma unicity_of_evaluation: assumes a: "e ⇓ e🪙1" and b: "e ⇓ e🪙2" shows"e🪙1 = e🪙2" using a b proof (nominal_induct e e🪙1 avoiding: e🪙2 rule: big.strong_induct) case (b_Lam x e t🪙2) have"Lam [x].e ⇓ t🪙2"by fact thus"Lam [x].e = t🪙2"by cases (simp_all add: trm.inject) next case (b_App x e🪙1 e🪙2 e' e🪙1' e🪙2' t🪙2) have ih1: "∧t. e🪙1 ⇓ t ==> Lam [x].e🪙1' = t"by fact have ih2:"∧t. e🪙2 ⇓ t ==> e🪙2' = t"by fact have ih3: "∧t. e🪙1'[x::=e🪙2'] ⇓ t ==> e' = t"by fact have app: "App e🪙1 e🪙2 ⇓ t🪙2"by fact have vc: "x♯e🪙1""x♯e🪙2""x♯t🪙2"by fact+ thenhave"x♯App e🪙1 e🪙2"by auto from app vc obtain f🪙1 f🪙2 where x1: "e🪙1 ⇓ Lam [x]. f🪙1"and x2: "e🪙2 ⇓ f🪙2"and x3: "f🪙1[x::=f🪙2] ⇓ t🪙2" by (auto elim!: b_App_elim) thenhave"Lam [x]. f🪙1 = Lam [x]. e🪙1'"using ih1 by simp then have"f🪙1 = e🪙1'"by (auto simp add: trm.inject alpha) moreover have"f🪙2 = e🪙2'"using x2 ih2 by simp ultimatelyhave"e🪙1'[x::=e🪙2'] ⇓ t🪙2"using x3 by simp thus"e' = t🪙2"using ih3 by simp qed
lemma reduces_evaluates_to_values: assumes h: "t ⇓ t'" shows"val t'" using h by (induct) (auto)
(* Valuation *)
nominal_primrec
V :: "ty ==> trm set" where "V (TVar x) = {e. val e}"
| "V (T🪙1 → T🪙2) = {Lam [x].e | x e. ∀ v ∈ (V T🪙1). ∃ v'. e[x::=v] ⇓ v' ∧ v' ∈ V T🪙2}" by (rule TrueI)+
lemma V_eqvt: fixes pi::"name prm" assumes"x ∈ V T" shows"(pi∙x) ∈ V T" using assms proof (nominal_induct T arbitrary: pi x rule: ty.strong_induct) case (TVar nat) thenshow ?case by (simp add: val.eqvt) next case (Arrow T🪙1 T🪙2 pi x) obtain a e where ae: "x = Lam [a]. e""∀v∈V T🪙1. ∃v'. e[a::=v] ⇓ v' ∧ v' ∈ V T🪙2" using Arrow.prems by auto have"∃v'. (pi ∙ e)[(pi ∙ a)::=v] ⇓ v' ∧ v' ∈ V T🪙2"if v: "v ∈ V T🪙1"for v proof - have"rev pi ∙ v ∈ V T🪙1" by (simp add: Arrow.hyps(1) v) thenobtain v' where"e[a::=(rev pi ∙ v)] ⇓ v'""v' ∈ V T🪙2" using ae(2) by blast thenhave"(pi ∙ e)[(pi ∙ a)::=v] ⇓ pi ∙ v'" by (metis (no_types, lifting) big.eqvt cons_eqvt nil_eqvt perm_pi_simp(1) perm_prod.simps psubst_eqvt) thenshow ?thesis using Arrow.hyps ‹v' ∈ V T🪙2›by blast qed with ae show ?caseby force qed
lemma V_arrow_elim_weak: assumes h:"u ∈ V (T🪙1 → T🪙2)" obtains a t where"u = Lam [a].t"and"∀ v ∈ (V T🪙1). ∃ v'. t[a::=v] ⇓ v' ∧ v' ∈ V T🪙2" using h by (auto)
lemma V_arrow_elim_strong: fixes c::"'a::fs_name" assumes h: "u ∈ V (T🪙1 → T🪙2)" obtains a t where"a♯c""u = Lam [a].t""∀v ∈ (V T🪙1). ∃ v'. t[a::=v] ⇓ v' ∧ v' ∈ V T??2" proof - obtain a t where"u = Lam [a].t" and at: "∧v. v ∈ (V T🪙1) ==>∃ v'. t[a::=v] ⇓ v' ∧ v' ∈ V T🪙2" using V_arrow_elim_weak [OF assms] by metis obtain a'::name where a': "a'♯(a,t,c)" by (meson exists_fresh fs_name_class.axioms) thenhave"u = Lam [a'].([(a, a')] ∙ t)" unfolding‹u = Lam [a].t› by (smt (verit) alpha fresh_atm fresh_prod perm_swap trm.inject(2)) moreover have"∃ v'. ([(a, a')] ∙ t)[a'::=v] ⇓ v' ∧ v' ∈ V T🪙2"if"v ∈ (V T🪙1)"for v proof - obtain v' where v': "t[a::=([(a, a')] ∙ v)] ⇓ v' ∧ v' ∈ V T🪙2" using V_eqvt ‹v ∈ V T🪙1› at by blast thenhave"([(a, a')] ∙ t[a::=([(a, a')] ∙ v)]) ⇓ [(a, a')] ∙ v'" by (simp add: big.eqvt) thenshow ?thesis by (smt (verit) V_eqvt cons_eqvt nil_eqvt perm_prod.simps perm_swap(1) psubst_eqvt swap_simps(1) v') qed ultimatelyshow thesis by (metis fresh_prod that a') qed
lemma Vs_are_values: assumes a: "e ∈ V T" shows"val e" using a by (nominal_induct T arbitrary: e rule: ty.strong_induct) (auto)
lemma values_reduce_to_themselves: assumes a: "val v" shows"v ⇓ v" using a by (induct) (auto)
lemma Vs_reduce_to_themselves: assumes a: "v ∈ V T" shows"v ⇓ v" using a by (simp add: values_reduce_to_themselves Vs_are_values)
text‹'θ maps x to e' asserts that θ substitutes x with e› abbreviation
mapsto :: "(name×trm) list ==> name ==> trm ==> bool" (‹_ maps _ to _› [55,55,55] 55) where "θ maps x to e ≡ (lookup θ x) = e"
abbreviation
v_closes :: "(name×trm) list ==> (name×ty) list ==> bool" (‹_ Vcloses _› [55,55] 55) where "θ Vcloses Γ ≡∀x T. (x,T) ∈ set Γ ⟶ (∃v. θ maps x to v ∧ v ∈ V T)"
lemma case_distinction_on_context: fixes Γ::"(name×ty) list" assumes asm1: "valid ((m,t)#Γ)" and asm2: "(n,U) ∈ set ((m,T)#Γ)" shows"(n,U) = (m,T) ∨ ((n,U) ∈ set Γ ∧ n ≠ m)" proof - from asm2 have"(n,U) ∈ set [(m,T)] ∨ (n,U) ∈ set Γ"by auto moreover
{ assume eq: "m=n" assume"(n,U) ∈ set Γ" thenhave"¬ n♯Γ" by (induct Γ) (auto simp add: fresh_list_cons fresh_prod fresh_atm) moreoverhave"m♯Γ"using asm1 by auto ultimatelyhave False using eq by auto
} ultimatelyshow ?thesis by auto qed
lemma monotonicity: fixes m::"name" fixes θ::"(name × trm) list" assumes h1: "θ Vcloses Γ" and h2: "e ∈ V T" and h3: "valid ((x,T)#Γ)" shows"(x,e)#θ Vcloses (x,T)#Γ" proof(intro strip) fix x' T' assume"(x',T') ∈ set ((x,T)#Γ)" thenhave"((x',T')=(x,T)) ∨ ((x',T')∈set Γ ∧ x'≠x)"using h3 by (rule_tac case_distinction_on_context) moreover
{ (* first case *) assume"(x',T') = (x,T)" thenhave"∃e'. ((x,e)#θ) maps x to e' ∧ e' ∈ V T'"using h2 by auto
} moreover
{ (* second case *) assume"(x',T') ∈ set Γ"and neq:"x' ≠ x" thenhave"∃e'. θ maps x' to e' ∧ e' ∈ V T'"using h1 by auto thenhave"∃e'. ((x,e)#θ) maps x' to e' ∧ e' ∈ V T'"using neq by auto
} ultimatelyshow"∃e'. ((x,e)#θ) maps x' to e' ∧ e' ∈ V T'"by blast qed
lemma termination_aux: assumes h1: "Γ ⊨ e : T" and h2: "θ Vcloses Γ" shows"∃v. θ⇓ v ∧ v ∈ V T" using h2 h1 proof(nominal_induct e avoiding: Γ θ arbitrary: T rule: trm.strong_induct) case (App e🪙1 e🪙2 Γ θ T) have ih🪙1: "∧θ Γ T. [θ Vcloses Γ; Γ ⊨ e🪙1 : T]==>∃v. θ🪙1> ⇓ v ∧ v ∈ V T" by fact have ih🪙2: "∧θ Γ T. [θ Vcloses Γ; Γ ⊨ e🪙2 : T]==>∃v. θ🪙2> ⇓ v ∧ v ∈ V T" by fact have as🪙1: "θ Vcloses Γ"by fact have as🪙2: "Γ ⊨ App e🪙1 e🪙2 : T"by fact thenobtain T' where"Γ ⊨ e🪙1 : T' → T"and"Γ ⊨ e🪙2 : T'"by (auto elim: t_App_elim) thenobtain v🪙1 v🪙2 where"(i)": "θ🪙1> ⇓ v🪙1" "v🪙1 ∈ V (T' → T)" and"(ii)": "θ🪙2> ⇓ v🪙2" "v🪙2 ∈ V T'"using ih🪙1 ih🪙2 as🪙1 by blast from"(i)"obtain x e' where"v🪙1 = Lam [x].e'" and"(iii)": "(∀v ∈ (V T').∃ v'. e'[x::=v] ⇓ v' ∧ v' ∈ V T)" and"(iv)": "θ🪙1> ⇓ Lam [x].e'" and fr: "x♯(θ,e🪙1,e🪙2)"by (blast elim: V_arrow_elim_strong) from fr have fr🪙1: "x♯θ🪙1>" and fr🪙2: "x♯θ🪙2>" by (simp_all add: fresh_psubst) from"(ii)""(iii)"obtain v🪙3 where"(v)": "e'[x::=v🪙2] ⇓ v🪙3""v🪙3 ∈ V T"by auto from fr🪙2 "(ii)"have"x♯v🪙2"by (simp add: big_preserves_fresh) thenhave"x♯e'[x::=v🪙2]"by (simp add: fresh_subst) thenhave fr🪙3: "x♯v🪙3"using"(v)"by (simp add: big_preserves_fresh) from fr🪙1 fr🪙2 fr🪙3 have"x♯(θ🪙1>,θ🪙2>,v🪙3)" by simp with"(iv)""(ii)""(v)"have"App (θ🪙1>) (θ🪙2>) ⇓ v🪙3" by auto thenshow"∃v. θ🪙1 e🪙2> ⇓ v ∧ v ∈ V T" using"(v)"by auto next case (Lam x e Γ θ T) have ih:"∧θ Γ T. [θ Vcloses Γ; Γ ⊨ e : T]==>∃v. θ⇓ v ∧ v ∈ V T"by fact have as🪙1: "θ Vcloses Γ"by fact have as🪙2: "Γ ⊨ Lam [x].e : T"by fact have fs: "x♯Γ""x♯θ"by fact+ from as🪙2 fs obtain T🪙1 T🪙2 where"(i)": "(x,T🪙1)#Γ ⊨ e:T🪙2"and"(ii)": "T = T🪙1 → T🪙2"using fs by (auto elim: t_Lam_elim) from"(i)"have"(iii)": "valid ((x,T🪙1)#Γ)"by (simp add: typing_implies_valid) have"∀v ∈ (V T🪙1). ∃v'. (θ)[x::=v] ⇓ v' ∧ v' ∈ V T🪙2" proof fix v assume"v ∈ (V T🪙1)" with"(iii)" as🪙1 have"(x,v)#θ Vcloses (x,T🪙1)#Γ"using monotonicity by auto with ih "(i)"obtain v' where"((x,v)#θ)⇓ v' ∧ v' ∈ V T🪙2"by blast thenhave"θ[x::=v] ⇓ v' ∧ v' ∈ V T🪙2"using fs by (simp add: psubst_subst_psubst) thenshow"∃v'. θ[x::=v] ⇓ v' ∧ v' ∈ V T🪙2"by auto qed thenhave"Lam[x].θ∈ V (T🪙1 → T🪙2)"by auto thenhave"θ⇓ Lam [x].θ∧ Lam [x].θ∈ V (T🪙1→T🪙2)"using fs by auto thus"∃v. θ⇓ v ∧ v ∈ V T"using"(ii)"by auto next case (Var x Γ θ T) have"Γ ⊨ (Var x) : T"by fact thenhave"(x,T)∈set Γ"by (cases) (auto simp add: trm.inject) with Var have"θ⇓ θ∧ θ∈ V T" by (auto intro!: Vs_reduce_to_themselves) thenshow"∃v. θ⇓ v ∧ v ∈ V T"by auto qed
theorem termination_of_evaluation: assumes a: "[] ⊨ e : T" shows"∃v. e ⇓ v ∧ val v" proof - from a have"∃v. []⇓ v ∧ v ∈ V T"by (rule termination_aux) (auto) thus"∃v. e ⇓ v ∧ val v"using Vs_are_values by auto qed
end
Messung V0.5 in Prozent
¤ Dauer der Verarbeitung: 0.39 Sekunden
(vorverarbeitet am 2026-05-03)
¤
Die Informationen auf dieser Webseite wurden
nach bestem Wissen sorgfältig zusammengestellt. Es wird jedoch weder Vollständigkeit, noch Richtigkeit,
noch Qualität der bereit gestellten Informationen zugesichert.
Bemerkung:
Die farbliche Syntaxdarstellung und die Messung sind noch experimentell.