(* *) (* Formalisation of the chapter on Logical Relations *) (* and a Case Study in Equivalence Checking *) (* by Karl Crary from the book on Advanced Topics in *) (* Types and Programming Languages, MIT Press 2005 *)
(* The formalisation was done by Julien Narboux and *) (* Christian Urban. *)
lemma lookup_fresh: fixes z::"name" assumes a: "z♯θ""z♯x" shows"z♯ lookup θ x" using a by (induct rule: lookup.induct)
(auto simp: fresh_list_cons)
lemma lookup_fresh': assumes a: "z♯θ" shows"lookup θ z = Var z" using a by (induct rule: lookup.induct)
(auto simp: fresh_list_cons fresh_prod fresh_atm)
lemma subst_eqvt[eqvt]: fixes pi::"name prm" shows"pi∙(t[x::=t']) = (pi∙t)[(pi∙x)::=(pi∙t')]" by (nominal_induct t avoiding: x t' rule: trm.strong_induct)
(perm_simp add: fresh_bij)+
lemma subst_rename: fixes c::"name" assumes a: "c♯t1" shows"t1[a::=t2] = ([(c,a)]∙t1)[c::=t2]" using a by (nominal_induct t1 avoiding: a c t2 rule: trm.strong_induct)
(auto simp: trm.inject calc_atm fresh_atm abs_fresh perm_nat_def)
lemma fresh_psubst: fixes z::"name" assumes a: "z♯t""z♯θ" shows"z♯(θ<t>)" using a by (nominal_induct t avoiding: z θ t rule: trm.strong_induct)
(auto simp: abs_fresh lookup_fresh)
lemma fresh_subst'': fixes z::"name" assumes"z♯t2" shows"z♯t1[z::=t2]" using assms by (nominal_induct t1 avoiding: t2 z rule: trm.strong_induct)
(auto simp: abs_fresh fresh_nat fresh_atm)
lemma fresh_subst': fixes z::"name" assumes"z♯[y].t1""z♯t2" shows"z♯t1[y::=t2]" using assms by (nominal_induct t1 avoiding: y t2 z rule: trm.strong_induct)
(auto simp: abs_fresh fresh_nat fresh_atm)
lemma fresh_subst: fixes z::"name" assumes a: "z♯t1""z♯t2" shows"z♯t1[y::=t2]" using a by (auto simp: fresh_subst' abs_fresh)
lemma fresh_psubst_simp: assumes"x♯t" shows"((x,u)#θ)<t> = θ<t>" using assms proof (nominal_induct t avoiding: x u θ rule: trm.strong_induct) case (Lam y t x u) have fs: "y♯θ""y♯x""y♯u"by fact+ moreoverhave"x♯ Lam [y].t"by fact ultimatelyhave"x♯t"by (simp add: abs_fresh fresh_atm) moreoverhave ih:"∧n T. n♯t ==> ((n,T)#θ)<t> = θ<t>"by fact ultimatelyhave"((x,u)#θ)<t> = θ<t>"by auto moreoverhave"((x,u)#θ)<Lam [y].t> = Lam [y].(((x,u)#θ)<t>)"using fs by (simp add: fresh_list_cons fresh_prod) moreoverhave" θ<Lam [y].t> = Lam [y]. (θ<t>)"using fs by simp ultimatelyshow"((x,u)#θ)<Lam [y].t> = θ<Lam [y].t>"by auto qed (auto simp: fresh_atm abs_fresh)
lemma forget: fixes x::"name" assumes a: "x♯t" shows"t[x::=t'] = t" using a by (nominal_induct t avoiding: x t' rule: trm.strong_induct)
(auto simp: fresh_atm abs_fresh)
lemma subst_fun_eq: fixes u::trm assumes h:"[x].t1 = [y].t2" shows"t1[x::=u] = t2[y::=u]" proof -
{ assume"x=y"and"t1=t2" thenhave ?thesis using h by simp
} moreover
{ assume h1:"x ≠ y"and h2:"t1=[(x,y)] ∙ t2"and h3:"x ♯ t2" thenhave"([(x,y)] ∙ t2)[x::=u] = t2[y::=u]"by (simp add: subst_rename) thenhave ?thesis using h2 by simp
} ultimatelyshow ?thesis using alpha h by blast qed
lemma psubst_empty[simp]: shows"[]<t> = t" by (nominal_induct t rule: trm.strong_induct)
(auto simp: fresh_list_nil)
lemma psubst_subst_psubst: assumes h:"c♯θ" shows"θ<t>[c::=s] = ((c,s)#θ)<t>" using h by (nominal_induct t avoiding: θ c s rule: trm.strong_induct)
(auto simp: fresh_list_cons fresh_atm forget lookup_fresh lookup_fresh' fresh_psubst)
lemma subst_fresh_simp: assumes a: "x♯θ" shows"θ<Var x> = Var x" using a by (induct θ arbitrary: x) (auto simp:fresh_list_cons fresh_prod fresh_atm)
lemma psubst_subst_propagate: assumes"x♯θ" shows"θ<t[x::=u]> = θ<t>[x::=θ<u>]" using assms proof (nominal_induct t avoiding: x u θ rule: trm.strong_induct) case (Var n x u θ)
{ assume"x=n" moreoverhave"x♯θ"by fact ultimatelyhave"θ<Var n[x::=u]> = θ<Var n>[x::=θ<u>]"using subst_fresh_simp by auto
} moreover
{ assume h:"x≠n" thenhave"x♯Var n"by (auto simp: fresh_atm) moreoverhave"x♯θ"by fact ultimatelyhave"x♯θ<Var n>"using fresh_psubst by blast thenhave" θ<Var n>[x::=θ<u>] = θ<Var n>"using forget by auto thenhave"θ<Var n[x::=u]> = θ<Var n>[x::=θ<u>]"using h by auto
} ultimatelyshow ?caseby auto next case (Lam n t x u θ) have fs:"n♯x""n♯u""n♯θ""x♯θ"by fact+ have ih:"∧ y s θ. y♯θ ==> ((θ<(t[y::=s])>) = ((θ<t>)[y::=(θ<s>)]))"by fact have"θ <(Lam [n].t)[x::=u]> = θ<Lam [n]. (t [x::=u])>"using fs by auto thenhave"θ <(Lam [n].t)[x::=u]> = Lam [n]. θ<t [x::=u]>"using fs by auto moreoverhave"θ<t[x::=u]> = θ<t>[x::=θ<u>]"using ih fs by blast ultimatelyhave"θ <(Lam [n].t)[x::=u]> = Lam [n].(θ<t>[x::=θ<u>])"by auto moreoverhave"Lam [n].(θ<t>[x::=θ<u>]) = (Lam [n].θ<t>)[x::=θ<u>]"using fs fresh_psubst by auto ultimatelyhave"θ<(Lam [n].t)[x::=u]> = (Lam [n].θ<t>)[x::=θ<u>]"using fs by auto thenshow"θ<(Lam [n].t)[x::=u]> = θ<Lam [n].t>[x::=θ<u>]"using fs by auto qed (auto)
lemma valid_monotonicity[elim]: fixes Γ Γ' :: Ctxt assumes a: "Γ ⊆ Γ'" and b: "x♯Γ'" shows"(x,T1)#Γ ⊆ (x,T1)#Γ'" using a b by auto
lemma fresh_context: fixes Γ :: "Ctxt" and a :: "name" assumes"a♯Γ" shows"¬(∃τ::ty. (a,τ)∈set Γ)" using assms by (induct Γ)
(auto simp: fresh_prod fresh_list_cons fresh_atm)
lemma type_unicity_in_context: assumes a: "valid Γ" and b: "(x,T1) ∈ set Γ" and c: "(x,T2) ∈ set Γ" shows"T1=T2" using a b c by (induct Γ)
(auto dest!: fresh_context)
abbreviation
nf :: "trm → bool" (‹_ ↝|› [100] 100) where "t↝| ≡¬(∃ u. t ↝ u)"
inductive
whn_def :: "trm→trm→bool" (‹_ ⇓ _› [80,80] 80) where
QAN_Reduce[intro]: "[s ↝ t; t ⇓ u]==> s ⇓ u"
| QAN_Normal[intro]: "t↝| ==> t ⇓ t"
declare trm.inject[simp]
inductive_cases whn_inv_auto[elim]: "t ⇓ t'"
declare trm.inject[simp del]
equivariance whn_def
lemma red_unicity : assumes a: "x ↝ a" and b: "x ↝ b" shows"a=b" using a b by (induct arbitrary: b) (use subst_fun_eq in blast)+
lemma nf_unicity : assumes"x ⇓ a"and"x ⇓ b" shows"a=b" using assms proof (induct arbitrary: b) case (QAN_Reduce x t a b) have h:"x ↝ t""t ⇓ a"by fact+ have ih:"∧b. t ⇓ b ==> a = b"by fact obtain t' where"x ↝ t'"and hl:"t' ⇓ b"using h ‹x ⇓ b›by auto thenhave"t=t'"using h red_unicity by auto thenshow"a=b"using ih hl by auto qed (auto)
section‹Algorithmic Term Equivalence and Algorithmic Path Equivalence›
inductive
alg_equiv :: "Ctxt→trm→trm→ty→bool" (‹_ ⊨ _ ⇔ _ : _› [60,60,60,60] 60) and
alg_path_equiv :: "Ctxt→trm→trm→ty→bool" (‹_ ⊨ _ ↔ _ : _› [60,60,60,60] 60) where
QAT_Base[intro]: "[s ⇓ p; t ⇓ q; Γ ⊨ p ↔ q : TBase]==> Γ ⊨ s ⇔ t : TBase"
| QAT_Arrow[intro]: "[x♯(Γ,s,t); (x,T1)#Γ ⊨ App s (Var x) ⇔ App t (Var x) : T2] ==> Γ ⊨ s ⇔ t : T1→ T2"
| QAT_One[intro]: "valid Γ ==> Γ ⊨ s ⇔ t : TUnit"
| QAP_Var[intro]: "[valid Γ;(x,T) ∈ set Γ]==> Γ ⊨ Var x ↔ Var x : T"
| QAP_App[intro]: "[Γ ⊨ p ↔ q : T1→ T2; Γ ⊨ s ⇔ t : T1]==> Γ ⊨ App p s ↔ App q t : T2"
| QAP_Const[intro]: "valid Γ ==> Γ ⊨ Const n ↔ Const n : TBase"
equivariance alg_equiv
nominal_inductive alg_equiv avoids QAT_Arrow: x by simp_all
"Γ ⊨ Var x ↔ t : T" "Γ ⊨ Var x ↔ t : T'" "Γ ⊨ s ↔ Var x : T" "Γ ⊨ s ↔ Var x : T'" "Γ ⊨ Const n ↔ t : T" "Γ ⊨ s ↔ Const n : T" "Γ ⊨ App p s ↔ t : T" "Γ ⊨ s ↔ App q t : T" "Γ ⊨ Lam[x].s ↔ t : T" "Γ ⊨ t ↔ Lam[x].s : T"
lemma Q_Arrow_strong_inversion: assumes fs: "x♯Γ""x♯t""x♯u" and h: "Γ ⊨ t ⇔ u : T1→T2" shows"(x,T1)#Γ ⊨ App t (Var x) ⇔ App u (Var x) : T2" proof - obtain y where fs2: "y♯(Γ,t,u)"and"(y,T1)#Γ ⊨ App t (Var y) ⇔ App u (Var y) : T2" using h by auto thenhave"([(x,y)]∙((y,T1)#Γ)) ⊨ [(x,y)]∙ App t (Var y) ⇔ [(x,y)]∙ App u (Var y) : T2" using alg_equiv.eqvt[simplified] by blast thenshow ?thesis using fs fs2 by (perm_simp) qed
lemma algorithmic_path_type_unicity: shows"Γ ⊨ s ↔ t : T ==> Γ ⊨ s ↔ u : T' ==> T = T'" proof (induct arbitrary: u T'
rule: alg_equiv_alg_path_equiv.inducts(2) [of _ _ _ _ _ "%a b c d . True" ]) case (QAP_Var Γ x T u T') have"Γ ⊨ Var x ↔ u : T'"by fact thenhave"u=Var x"and"(x,T') ∈ set Γ"by auto moreoverhave"valid Γ""(x,T) ∈ set Γ"by fact+ ultimatelyshow"T=T'"using type_unicity_in_context by auto next case (QAP_App Γ p q T1 T2 s t u T2') have ih:"∧u T. Γ ⊨ p ↔ u : T ==> T1→T2 = T"by fact have"Γ ⊨ App p s ↔ u : T2'"by fact thenobtain r t T1' where"u = App r t""Γ ⊨ p ↔ r : T1' → T2'"by auto with ih have"T1→T2 = T1' → T2'"by auto thenshow"T2=T2'"using ty.inject by auto qed (auto)
lemma alg_path_equiv_implies_valid: shows"Γ ⊨ s ⇔ t : T ==> valid Γ" and"Γ ⊨ s ↔ t : T ==> valid Γ" by (induct rule : alg_equiv_alg_path_equiv.inducts) auto
lemma algorithmic_symmetry: shows"Γ ⊨ s ⇔ t : T ==> Γ ⊨ t ⇔ s : T" and"Γ ⊨ s ↔ t : T ==> Γ ⊨ t ↔ s : T" by (induct rule: alg_equiv_alg_path_equiv.inducts)
(auto simp: fresh_prod)
lemma algorithmic_transitivity: shows"Γ ⊨ s ⇔ t : T ==> Γ ⊨ t ⇔ u : T ==> Γ ⊨ s ⇔ u : T" and"Γ ⊨ s ↔ t : T ==> Γ ⊨ t ↔ u : T ==> Γ ⊨ s ↔ u : T" proof (nominal_induct Γ s t T and Γ s t T avoiding: u rule: alg_equiv_alg_path_equiv.strong_inducts) case (QAT_Base s p t q Γ u) have"Γ ⊨ t ⇔ u : TBase"by fact thenobtain r' q' where b1: "t ⇓ q'"and b2: "u ⇓ r'"and b3: "Γ ⊨ q' ↔ r' : TBase"by auto have ih: "Γ ⊨ q ↔ r' : TBase ==> Γ ⊨ p ↔ r' : TBase"by fact have"t ⇓ q"by fact with b1 have eq: "q=q'"by (simp add: nf_unicity) with ih b3 have"Γ ⊨ p ↔ r' : TBase"by simp moreover have"s ⇓ p"by fact ultimatelyshow"Γ ⊨ s ⇔ u : TBase"using b2 by auto next case (QAT_Arrow x Γ s t T1 T2 u) have ih:"(x,T1)#Γ ⊨ App t (Var x) ⇔ App u (Var x) : T2 ==> (x,T1)#Γ ⊨ App s (Var x) ⇔ App u (Var x) : T2"by fact have fs: "x♯Γ""x♯s""x♯t""x♯u"by fact+ have"Γ ⊨ t ⇔ u : T1→T2"by fact thenhave"(x,T1)#Γ ⊨ App t (Var x) ⇔ App u (Var x) : T2"using fs by (simp add: Q_Arrow_strong_inversion) with ih have"(x,T1)#Γ ⊨ App s (Var x) ⇔ App u (Var x) : T2"by simp thenshow"Γ ⊨ s ⇔ u : T1→T2"using fs by (auto simp: fresh_prod) next case (QAP_App Γ p q T1 T2 s t u) have"Γ ⊨ App q t ↔ u : T2"by fact thenobtain r T1' v where ha: "Γ ⊨ q ↔ r : T1'→T2"and hb: "Γ ⊨ t ⇔ v : T1'"and eq: "u = App r v" by auto have ih1: "Γ ⊨ q ↔ r : T1→T2==> Γ ⊨ p ↔ r : T1→T2"by fact have ih2:"Γ ⊨ t ⇔ v : T1==> Γ ⊨ s ⇔ v : T1"by fact have"Γ ⊨ p ↔ q : T1→T2"by fact thenhave"Γ ⊨ q ↔ p : T1→T2"by (simp add: algorithmic_symmetry) with ha have"T1'→T2 = T1→T2"using algorithmic_path_type_unicity by simp thenhave"T1' = T1"by (simp add: ty.inject) thenhave"Γ ⊨ s ⇔ v : T1""Γ ⊨ p ↔ r : T1→T2"using ih1 ih2 ha hb by auto thenshow"Γ ⊨ App p s ↔ u : T2"using eq by auto qed (auto)
lemma algorithmic_weak_head_closure: shows"Γ ⊨ s ⇔ t : T ==> s' ↝ s ==> t' ↝ t ==> Γ ⊨ s' ⇔ t' : T" proof (nominal_induct Γ s t T avoiding: s' t'
rule: alg_equiv_alg_path_equiv.strong_inducts(1) [of _ _ _ _ "λa b c d e. True"]) qed(auto intro!: QAT_Arrow)
lemma algorithmic_monotonicity: shows"Γ ⊨ s ⇔ t : T ==> Γ ⊆ Γ' ==> valid Γ' ==> Γ' ⊨ s ⇔ t : T" and"Γ ⊨ s ↔ t : T ==> Γ ⊆ Γ' ==> valid Γ' ==> Γ' ⊨ s ↔ t : T" proof (nominal_induct Γ s t T and Γ s t T avoiding: Γ' rule: alg_equiv_alg_path_equiv.strong_inducts) case (QAT_Arrow x Γ s t T1 T2 Γ') have fs:"x♯Γ""x♯s""x♯t""x♯Γ'"by fact+ have h2:"Γ ⊆ Γ'"by fact have ih:"∧Γ'. [(x,T1)#Γ ⊆ Γ'; valid Γ']==> Γ' ⊨ App s (Var x) ⇔ App t (Var x) : T2"by fact have"valid Γ'"by fact thenhave"valid ((x,T1)#Γ')"using fs by auto moreover have sub: "(x,T1)#Γ ⊆ (x,T1)#Γ'"using h2 by auto ultimatelyhave"(x,T1)#Γ' ⊨ App s (Var x) ⇔ App t (Var x) : T2"using ih by simp thenshow"Γ' ⊨ s ⇔ t : T1→T2"using fs by (auto simp: fresh_prod) qed (auto)
lemma path_equiv_implies_nf: assumes"Γ ⊨ s ↔ t : T" shows"s ↝|"and"t ↝|" using assms by (induct rule: alg_equiv_alg_path_equiv.inducts(2)) (simp, auto)
section‹Logical Equivalence›
function log_equiv :: "(Ctxt → trm → trm → ty → bool)" (‹_ ⊨ _ is _ : _› [60,60,60,60] 60) where "Γ ⊨ s is t : TUnit = True"
| "Γ ⊨ s is t : TBase = Γ ⊨ s ⇔ t : TBase"
| "Γ ⊨ s is t : (T1→ T2) = (∀Γ' s' t'. Γ⊆Γ' ⟶ valid Γ' ⟶ Γ' ⊨ s' is t' : T1⟶ (Γ' ⊨ (App s s') is (App t t') : T2))" using ty_cases by (force simp: ty.inject)+
terminationby lexicographic_order
lemma logical_monotonicity: fixes Γ Γ' :: Ctxt assumes a1: "Γ ⊨ s is t : T" and a2: "Γ ⊆ Γ'" and a3: "valid Γ'" shows"Γ' ⊨ s is t : T" using a1 a2 a3 proof (induct arbitrary: Γ' rule: log_equiv.induct) case (2 Γ s t Γ') thenshow"Γ' ⊨ s is t : TBase"using algorithmic_monotonicity by auto next case (3 Γ s t T1 T2 Γ') have"Γ ⊨ s is t : T1→T2" and"Γ ⊆ Γ'" and"valid Γ'"by fact+ thenshow"Γ' ⊨ s is t : T1→T2"by simp qed (auto)
lemma main_lemma: shows"Γ ⊨ s is t : T ==> valid Γ ==> Γ ⊨ s ⇔ t : T" and"Γ ⊨ p ↔ q : T ==> Γ ⊨ p is q : T" proof (nominal_induct T arbitrary: Γ s t p q rule: ty.strong_induct) case (Arrow T1 T2)
{ case (1 Γ s t) have ih1:"∧Γ s t. [Γ ⊨ s is t : T2; valid Γ]==> Γ ⊨ s ⇔ t : T2"by fact have ih2:"∧Γ s t. Γ ⊨ s ↔ t : T1==> Γ ⊨ s is t : T1"by fact have h:"Γ ⊨ s is t : T1→T2"by fact obtain x::name where fs:"x♯(Γ,s,t)"by (erule exists_fresh[OF fs_name1]) have"valid Γ"by fact thenhave v: "valid ((x,T1)#Γ)"using fs by auto thenhave"(x,T1)#Γ ⊨ Var x ↔ Var x : T1"by auto thenhave"(x,T1)#Γ ⊨ Var x is Var x : T1"using ih2 by auto thenhave"(x,T1)#Γ ⊨ App s (Var x) is App t (Var x) : T2"using h v by auto thenhave"(x,T1)#Γ ⊨ App s (Var x) ⇔ App t (Var x) : T2"using ih1 v by auto thenshow"Γ ⊨ s ⇔ t : T1→T2"using fs by (auto simp: fresh_prod) next case (2 Γ p q) have h: "Γ ⊨ p ↔ q : T1→T2"by fact have ih1:"∧Γ s t. Γ ⊨ s ↔ t : T2==> Γ ⊨ s is t : T2"by fact have ih2:"∧Γ s t. [Γ ⊨ s is t : T1; valid Γ]==> Γ ⊨ s ⇔ t : T1"by fact
{ fix Γ' s t assume"Γ ⊆ Γ'"and hl:"Γ' ⊨ s is t : T1"and hk: "valid Γ'" thenhave"Γ' ⊨ p ↔ q : T1→ T2"using h algorithmic_monotonicity by auto moreoverhave"Γ' ⊨ s ⇔ t : T1"using ih2 hl hk by auto ultimatelyhave"Γ' ⊨ App p s ↔ App q t : T2"by auto thenhave"Γ' ⊨ App p s is App q t : T2"using ih1 by auto
} thenshow"Γ ⊨ p is q : T1→T2"by simp
} next case TBase
{ case2 have h:"Γ ⊨ s ↔ t : TBase"by fact thenhave"s ↝|"and"t ↝|"using path_equiv_implies_nf by auto thenhave"s ⇓ s"and"t ⇓ t"by auto thenhave"Γ ⊨ s ⇔ t : TBase"using h by auto thenshow"Γ ⊨ s is t : TBase"by auto
} qed (auto elim: alg_path_equiv_implies_valid)
corollary corollary_main: assumes a: "Γ ⊨ s ↔ t : T" shows"Γ ⊨ s ⇔ t : T" using a main_lemma alg_path_equiv_implies_valid by blast
lemma logical_symmetry: assumes a: "Γ ⊨ s is t : T" shows"Γ ⊨ t is s : T" using a by (nominal_induct arbitrary: Γ s t rule: ty.strong_induct)
(auto simp: algorithmic_symmetry)
lemma logical_transitivity: assumes"Γ ⊨ s is t : T""Γ ⊨ t is u : T" shows"Γ ⊨ s is u : T" using assms proof (nominal_induct arbitrary: Γ s t u rule:ty.strong_induct) case TBase thenshow"Γ ⊨ s is u : TBase"by (auto elim: algorithmic_transitivity) next case (Arrow T1 T2 Γ s t u) have h1:"Γ ⊨ s is t : T1→ T2"by fact have h2:"Γ ⊨ t is u : T1→ T2"by fact have ih1:"∧Γ s t u. [Γ ⊨ s is t : T1; Γ ⊨ t is u : T1]==> Γ ⊨ s is u : T1"by fact have ih2:"∧Γ s t u. [Γ ⊨ s is t : T2; Γ ⊨ t is u : T2]==> Γ ⊨ s is u : T2"by fact
{ fix Γ' s' u' assume hsub:"Γ ⊆ Γ'"and hl:"Γ' ⊨ s' is u' : T1"and hk: "valid Γ'" thenhave"Γ' ⊨ u' is s' : T1"using logical_symmetry by blast thenhave"Γ' ⊨ u' is u' : T1"using ih1 hl by blast thenhave"Γ' ⊨ App t u' is App u u' : T2"using h2 hsub hk by auto moreoverhave"Γ' ⊨ App s s' is App t u' : T2"using h1 hsub hl hk by auto ultimatelyhave"Γ' ⊨ App s s' is App u u' : T2"using ih2 by blast
} thenshow"Γ ⊨ s is u : T1→ T2"by auto qed (auto)
lemma logical_weak_head_closure: assumes a: "Γ ⊨ s is t : T" and b: "s' ↝ s" and c: "t' ↝ t" shows"Γ ⊨ s' is t' : T" using a b c algorithmic_weak_head_closure proof (nominal_induct arbitrary: Γ s t s' t' rule: ty.strong_induct) next case (Arrow ty1 ty2) thenshow ?case by (smt (verit, ccfv_threshold) QAR_App log_equiv.simps(3)) qed auto
lemma logical_weak_head_closure': assumes"Γ ⊨ s is t : T"and"s' ↝ s" shows"Γ ⊨ s' is t : T" using assms proof (nominal_induct arbitrary: Γ s t s' rule: ty.strong_induct) case (TBase Γ s t s') thenshow ?caseby force next case (TUnit Γ s t s') thenshow ?caseby auto next case (Arrow T1 T2 Γ s t s') have h1:"s' ↝ s"by fact have ih:"∧Γ s t s'. [Γ ⊨ s is t : T2; s' ↝ s]==> Γ ⊨ s' is t : T2"by fact have h2:"Γ ⊨ s is t : T1→T2"by fact then have hb:"∀Γ' s' t'. Γ⊆Γ' ⟶ valid Γ' ⟶ Γ' ⊨ s' is t' : T1⟶ (Γ' ⊨ (App s s') is (App t t') : T2)" by auto
{ fix Γ' s2 t2 assume"Γ ⊆ Γ'"and"Γ' ⊨ s2 is t2 : T1"and"valid Γ'" thenhave"Γ' ⊨ (App s s2) is (App t t2) : T2"using hb by auto moreoverhave"(App s' s2) ↝ (App s s2)"using h1 by auto ultimatelyhave"Γ' ⊨ App s' s2 is App t t2 : T2"using ih by auto
} thenshow"Γ ⊨ s' is t : T1→T2"by auto qed
abbreviation
log_equiv_for_psubsts :: "Ctxt → Subst → Subst → Ctxt → bool" (‹_ ⊨ _ is _ over _› [60,60] 60) where "Γ' ⊨ θ is θ' over Γ ≡∀x T. (x,T) ∈ set Γ ⟶ Γ' ⊨ θ<Var x> is θ'<Var x> : T"
lemma logical_pseudo_reflexivity: assumes"Γ' ⊨ t is s over Γ" shows"Γ' ⊨ s is s over Γ" by (meson assms logical_symmetry logical_transitivity)
lemma logical_subst_monotonicity : fixes Γ Γ' Γ'' :: Ctxt assumes a: "Γ' ⊨ θ is θ' over Γ" and b: "Γ' ⊆ Γ''" and c: "valid Γ''" shows"Γ'' ⊨ θ is θ' over Γ" using a b c logical_monotonicity by blast
lemma equiv_subst_ext : assumes h1: "Γ' ⊨ θ is θ' over Γ" and h2: "Γ' ⊨ s is t : T" and fs: "x♯Γ" shows"Γ' ⊨ (x,s)#θ is (x,t)#θ' over (x,T)#Γ" using assms proof -
{ fix y U assume"(y,U) ∈ set ((x,T)#Γ)" moreover
{ assume"(y,U) ∈ set [(x,T)]" with h2 have"Γ' ⊨ ((x,s)#θ)<Var y> is ((x,t)#θ')<Var y> : U"by auto
} moreover
{ assume hl:"(y,U) ∈ set Γ" thenhave"¬ y♯Γ"by (induct Γ) (auto simp: fresh_list_cons fresh_atm fresh_prod) thenhave hf:"x♯ Var y"using fs by (auto simp: fresh_atm) thenhave"((x,s)#θ)<Var y> = θ<Var y>""((x,t)#θ')<Var y> = θ'<Var y>" using fresh_psubst_simp by blast+ moreoverhave"Γ' ⊨ θ<Var y> is θ'<Var y> : U"using h1 hl by auto ultimatelyhave"Γ' ⊨ ((x,s)#θ)<Var y> is ((x,t)#θ')<Var y> : U"by auto
} ultimatelyhave"Γ' ⊨ ((x,s)#θ)<Var y> is ((x,t)#θ')<Var y> : U"by auto
} thenshow"Γ' ⊨ (x,s)#θ is (x,t)#θ' over (x,T)#Γ"by auto qed
theorem fundamental_theorem_1: assumes a1: "Γ ⊨ t : T" and a2: "Γ' ⊨ θ is θ' over Γ" and a3: "valid Γ'" shows"Γ' ⊨ θ<t> is θ'<t> : T" using a1 a2 a3 proof (nominal_induct Γ t T avoiding: θ θ' arbitrary: Γ' rule: typing.strong_induct) case (T_Lam x Γ T1 t2 T2 θ θ' Γ') have vc: "x♯θ""x♯θ'""x♯Γ"by fact+ have asm1: "Γ' ⊨ θ is θ' over Γ"by fact have ih:"∧θ θ' Γ'. [Γ' ⊨ θ is θ' over (x,T1)#Γ; valid Γ']==> Γ' ⊨ θ<t2> is θ'<t2> : T2"by fact show"Γ' ⊨ θ<Lam [x].t2> is θ'<Lam [x].t2> : T1→T2"using vc proof (simp, intro strip) fix Γ'' s' t' assume sub: "Γ' ⊆ Γ''" and asm2: "Γ''⊨ s' is t' : T1" and val: "valid Γ''" from asm1 val sub have"Γ'' ⊨ θ is θ' over Γ"using logical_subst_monotonicity by blast with asm2 vc have"Γ'' ⊨ (x,s')#θ is (x,t')#θ' over (x,T1)#Γ"using equiv_subst_ext by blast with ih val have"Γ'' ⊨ ((x,s')#θ)<t2> is ((x,t')#θ')<t2> : T2"by auto with vc have"Γ''⊨θ<t2>[x::=s'] is θ'<t2>[x::=t'] : T2"by (simp add: psubst_subst_psubst) moreover have"App (Lam [x].θ<t2>) s' ↝ θ<t2>[x::=s']"by auto moreover have"App (Lam [x].θ'<t2>) t' ↝ θ'<t2>[x::=t']"by auto ultimatelyshow"Γ''⊨ App (Lam [x].θ<t2>) s' is App (Lam [x].θ'<t2>) t' : T2" using logical_weak_head_closure by auto qed qed (auto)
theorem fundamental_theorem_2: assumes h1: "Γ ⊨ s ≡ t : T" and h2: "Γ' ⊨ θ is θ' over Γ" and h3: "valid Γ'" shows"Γ' ⊨ θ<s> is θ'<t> : T" using h1 h2 h3 proof (nominal_induct Γ s t T avoiding: Γ' θ θ' rule: def_equiv.strong_induct) case (Q_Refl Γ t T Γ' θ θ') thenshow"Γ' ⊨ θ<t> is θ'<t> : T"using fundamental_theorem_1 by blast next case (Q_Symm Γ t s T Γ' θ θ') thenshow"Γ' ⊨ θ<s> is θ'<t> : T"using logical_symmetry by blast next case (Q_Trans Γ s t T u Γ' θ θ') have ih1: "∧ Γ' θ θ'. [Γ' ⊨ θ is θ' over Γ; valid Γ']==> Γ' ⊨ θ<s> is θ'<t> : T"by fact have ih2: "∧ Γ' θ θ'. [Γ' ⊨ θ is θ' over Γ; valid Γ']==> Γ' ⊨ θ<t> is θ'<u> : T"by fact have h: "Γ' ⊨ θ is θ' over Γ" and v: "valid Γ'"by fact+ thenhave"Γ' ⊨ θ' is θ' over Γ"using logical_pseudo_reflexivity by auto thenhave"Γ' ⊨ θ'<t> is θ'<u> : T"using ih2 v by auto moreoverhave"Γ' ⊨ θ<s> is θ'<t> : T"using ih1 h v by auto ultimatelyshow"Γ' ⊨ θ<s> is θ'<u> : T"using logical_transitivity by blast next case (Q_Abs x Γ T1 s2 t2 T2 Γ' θ θ') have fs:"x♯Γ"by fact have fs2: "x♯θ""x♯θ'"by fact+ have h2: "Γ' ⊨ θ is θ' over Γ" and h3: "valid Γ'"by fact+ have ih:"∧Γ' θ θ'. [Γ' ⊨ θ is θ' over (x,T1)#Γ; valid Γ']==> Γ' ⊨ θ<s2> is θ'<t2> : T2"by fact
{ fix Γ'' s' t' assume"Γ' ⊆ Γ''"and hl:"Γ''⊨ s' is t' : T1"and hk: "valid Γ''" thenhave"Γ'' ⊨ θ is θ' over Γ"using h2 logical_subst_monotonicity by blast thenhave"Γ'' ⊨ (x,s')#θ is (x,t')#θ' over (x,T1)#Γ"using equiv_subst_ext hl fs by blast thenhave"Γ'' ⊨ ((x,s')#θ)<s2> is ((x,t')#θ')<t2> : T2"using ih hk by blast thenhave"Γ''⊨ θ<s2>[x::=s'] is θ'<t2>[x::=t'] : T2"using fs2 psubst_subst_psubst by auto moreoverhave"App (Lam [x]. θ<s2>) s' ↝ θ<s2>[x::=s']" and"App (Lam [x].θ'<t2>) t' ↝ θ'<t2>[x::=t']"by auto ultimatelyhave"Γ'' ⊨ App (Lam [x]. θ<s2>) s' is App (Lam [x].θ'<t2>) t' : T2" using logical_weak_head_closure by auto
} moreoverhave"valid Γ'"by fact ultimatelyhave"Γ' ⊨ Lam [x].θ<s2> is Lam [x].θ'<t2> : T1→T2"by auto thenshow"Γ' ⊨ θ<Lam [x].s2> is θ'<Lam [x].t2> : T1→T2"using fs2 by auto next case (Q_App Γ s1 t1 T1 T2 s2 t2 Γ' θ θ') thenshow"Γ' ⊨ θ<App s1 s2> is θ'<App t1 t2> : T2"by auto next case (Q_Beta x Γ s2 t2 T1 s12 t12 T2 Γ' θ θ') have h: "Γ' ⊨ θ is θ' over Γ" and h': "valid Γ'"by fact+ have fs: "x♯Γ"by fact have fs2: " x♯θ""x♯θ'"by fact+ have ih1: "∧Γ' θ θ'. [Γ' ⊨ θ is θ' over Γ; valid Γ']==> Γ' ⊨ θ<s2> is θ'<t2> : T1"by fact have ih2: "∧Γ' θ θ'. [Γ' ⊨ θ is θ' over (x,T1)#Γ; valid Γ']==> Γ' ⊨ θ<s12> is θ'<t12> : T2"by fact have"Γ' ⊨ θ<s2> is θ'<t2> : T1"using ih1 h' h by auto thenhave"Γ' ⊨ (x,θ<s2>)#θ is (x,θ'<t2>)#θ' over (x,T1)#Γ"using equiv_subst_ext h fs by blast thenhave"Γ' ⊨ ((x,θ<s2>)#θ)<s12> is ((x,θ'<t2>)#θ')<t12> : T2"using ih2 h' by auto thenhave"Γ' ⊨ θ<s12>[x::=θ<s2>] is θ'<t12>[x::=θ'<t2>] : T2"using fs2 psubst_subst_psubst byauto thenhave"Γ' ⊨ θ<s12>[x::=θ<s2>] is θ'<t12[x::=t2]> : T2"using fs2 psubst_subst_propagate by auto moreoverhave"App (Lam [x].θ<s12>) (θ<s2>) ↝ θ<s12>[x::=θ<s2>]"by auto ultimatelyhave"Γ' ⊨ App (Lam [x].θ<s12>) (θ<s2>) is θ'<t12[x::=t2]> : T2" using logical_weak_head_closure' by auto thenshow"Γ' ⊨ θ<App (Lam [x].s12) s2> is θ'<t12[x::=t2]> : T2"using fs2 by simp next case (Q_Ext x Γ s t T1 T2 Γ' θ θ') have h2: "Γ' ⊨ θ is θ' over Γ" and h2': "valid Γ'"by fact+ have fs:"x♯Γ""x♯s""x♯t"by fact+ have ih:"∧Γ' θ θ'. [Γ' ⊨ θ is θ' over (x,T1)#Γ; valid Γ'] ==> Γ' ⊨ θ<App s (Var x)> is θ'<App t (Var x)> : T2"by fact
{ fix Γ'' s' t' assume hsub: "Γ' ⊆ Γ''"and hl: "Γ''⊨ s' is t' : T1"and hk: "valid Γ''" thenhave"Γ'' ⊨ θ is θ' over Γ"using h2 logical_subst_monotonicity by blast thenhave"Γ'' ⊨ (x,s')#θ is (x,t')#θ' over (x,T1)#Γ"using equiv_subst_ext hl fs by blast thenhave"Γ'' ⊨ ((x,s')#θ)<App s (Var x)> is ((x,t')#θ')<App t (Var x)> : T2"using ih hk by blast then have"Γ'' ⊨ App (((x,s')#θ)<s>) (((x,s')#θ)<(Var x)>) is App (((x,t')#θ')<t>) (((x,t')#θ')<(Var x)>) : T2" by auto thenhave"Γ'' ⊨ App ((x,s')#θ)<s> s' is App ((x,t')#θ')<t> t' : T2"by auto thenhave"Γ'' ⊨ App (θ<s>) s' is App (θ'<t>) t' : T2"using fs fresh_psubst_simp by auto
} moreoverhave"valid Γ'"by fact ultimatelyshow"Γ' ⊨ θ<s> is θ'<t> : T1→T2"by auto next case (Q_Unit Γ s t Γ' θ θ') thenshow"Γ' ⊨ θ<s> is θ'<t> : TUnit"by auto qed
theorem completeness: assumes asm: "Γ ⊨ s ≡ t : T" shows"Γ ⊨ s ⇔ t : T" proof - have val: "valid Γ"using def_equiv_implies_valid asm by simp thenhave"Γ ⊨ [] is [] over Γ" by (simp add: QAP_Var main_lemma(2)) thenhave"Γ ⊨ []<s> is []<t> : T"using fundamental_theorem_2 val asm by blast thenhave"Γ ⊨ s is t : T"by simp thenshow"Γ ⊨ s ⇔ t : T"using main_lemma(1) val by simp qed
text‹We leave soundness as an exercise - just like Crary in the ATS book :-) \\
@{prop[mode=IfThen] "[Γ ⊨ s ⇔ t : T; Γ ⊨ t : T; Γ ⊨ s : T]==> Γ ⊨ s ≡ t : T"} \\ prop‹[Γ ⊨ s ↔ t : T; Γ ⊨ t : T; Γ ⊨ s : T]==> Γ ⊨ s ≡ t : T› ›
end
Messung V0.5 in Prozent
¤ Dauer der Verarbeitung: 0.21 Sekunden
(vorverarbeitet am 2026-06-30)
¤
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.