Skip to content

Commit 465167a

Browse files
authored
chore: cleanup of Cslib.Languages.LambdaCalculus.LocallyNameless.* (#250)
With the somewhat recent change to allow passing arbitrary expressions to `grind` and other improvements, some cleanup of locally nameless lambda calculus is possible.
1 parent 26c0474 commit 465167a

10 files changed

Lines changed: 97 additions & 172 deletions

File tree

Cslib/Languages/LambdaCalculus/LocallyNameless/Fsub/Opening.lean

Lines changed: 13 additions & 16 deletions
Original file line numberDiff line numberDiff line change
@@ -87,7 +87,7 @@ lemma openRec_neq_eq {σ τ γ : Ty Var} (neq : X ≠ Y) (h : σ⟦Y ↝ τ⟧
8787
/-- A locally closed type is unchanged by opening. -/
8888
lemma openRec_lc {σ τ : Ty Var} (lc : σ.LC) : σ = σ⟦X ↝ τ⟧ᵞ := by
8989
induction lc generalizing X with
90-
| all => have := fresh_exists <| free_union Var; grind [openRec_neq_eq]
90+
| all => grind [fresh_exists <| free_union Var, openRec_neq_eq]
9191
| _ => grind
9292

9393
omit [HasFresh Var] in
@@ -102,8 +102,7 @@ lemma subst_fresh (nmem : X ∉ γ.fv) (δ : Ty Var) : γ = γ[X := δ] := by
102102
/-- Substitution of a locally closed type distributes with opening. -/
103103
lemma openRec_subst (Y : ℕ) (σ τ : Ty Var) (lc : δ.LC) (X : Var) :
104104
(σ⟦Y ↝ τ⟧ᵞ)[X := δ] = σ[X := δ]⟦Y ↝ τ[X := δ]⟧ᵞ := by
105-
induction σ generalizing Y
106-
all_goals grind [openRec_lc]
105+
induction σ generalizing Y <;> grind [openRec_lc]
107106

108107
/-- Specialize `Ty.openRec_subst` to the first opening. -/
109108
lemma open_subst (σ τ : Ty Var) (lc : δ.LC) (X : Var) : (σ ^ᵞ τ)[X := δ] = σ[X := δ] ^ᵞ τ[X := δ]
@@ -125,9 +124,9 @@ lemma open_subst_intro (δ : Ty Var) (nmem : X ∉ γ.fv) : γ ^ᵞ δ = (γ ^
125124
openRec_subst_intro _ _ nmem
126125

127126
lemma subst_lc (σ_lc : σ.LC) (τ_lc : τ.LC) (X : Var) : σ[X := τ].LC := by
128-
induction σ_lc
129-
case all => apply LC.all (free_union Var) <;> grind [openRec_subst]
130-
all_goals grind [openRec_subst]
127+
induction σ_lc with
128+
| all => grind [LC.all (free_union Var), openRec_subst]
129+
| _ => grind [openRec_subst]
131130

132131
omit [HasFresh Var] in
133132
lemma nmem_fv_openRec (nmem : X ∉ (σ⟦k ↝ γ⟧ᵞ).fv) : X ∉ σ.fv := by
@@ -226,11 +225,10 @@ lemma openRec_tm_ty_eq (eq : t⟦x ↝ s⟧ᵗᵗ = t⟦x ↝ s⟧ᵗᵗ⟦y ↝
226225
/-- A locally closed term is unchanged by type opening. -/
227226
@[scoped grind =_]
228227
lemma openRec_ty_lc {t : Term Var} (lc : t.LC) : t = t⟦X ↝ σ⟧ᵗᵞ := by
229-
induction lc generalizing X
230-
case let' | case | tabs | abs =>
231-
have := fresh_exists <| free_union Var
232-
congr <;> grind [Ty.openRec_lc, openRec_ty_neq_eq]
233-
all_goals grind [Ty.openRec_lc]
228+
induction lc generalizing X with
229+
| let' | case | tabs | abs =>
230+
grind [fresh_exists <| free_union Var, Ty.openRec_lc, openRec_ty_neq_eq]
231+
| _ => grind [Ty.openRec_lc]
234232

235233
/-- Substitution of a type within a term. -/
236234
@[scoped grind =]
@@ -318,11 +316,10 @@ variable [HasFresh Var]
318316
/-- A locally closed term is unchanged by term opening. -/
319317
@[scoped grind =_]
320318
lemma openRec_tm_lc (lc : t.LC) : t = t⟦x ↝ s⟧ᵗᵗ := by
321-
induction lc generalizing x
322-
case let' | case | tabs | abs =>
323-
have := fresh_exists <| free_union Var
324-
congr <;> grind [openRec_tm_neq_eq, openRec_ty_tm_eq]
325-
all_goals grind
319+
induction lc generalizing x with
320+
| let' | case | tabs | abs =>
321+
grind [fresh_exists <| free_union Var, openRec_tm_neq_eq, openRec_ty_tm_eq]
322+
| _ => grind
326323

327324
variable {t s : Term Var} {δ : Ty Var} {x : Var}
328325

Cslib/Languages/LambdaCalculus/LocallyNameless/Fsub/Reduction.lean

Lines changed: 9 additions & 18 deletions
Original file line numberDiff line numberDiff line change
@@ -48,36 +48,27 @@ variable [DecidableEq Var]
4848
@[scoped grind _=_]
4949
lemma body_let : (let' t₁ t₂).LC ↔ t₁.LC ∧ t₂.body := by
5050
constructor <;> intro h <;> cases h
51-
case mp.let' L _ _ =>
52-
split_ands
53-
· grind
54-
· exists L
51+
case mp.let' L t₁_lc h => exact ⟨t₁_lc, L, h⟩
5552
case mpr.intro body =>
5653
obtain ⟨_, _⟩ := body
57-
apply LC.let' (free_union Var) <;> grind
54+
grind [LC.let' <| free_union Var]
5855

5956
/-- Locally closed case bindings have a locally closed bodies. -/
6057
@[scoped grind _=_]
6158
lemma body_case : (case t₁ t₂ t₃).LC ↔ t₁.LC ∧ t₂.body ∧ t₃.body := by
6259
constructor <;> intro h
63-
case mp =>
64-
cases h with | case L =>
65-
split_ands
66-
· grind
67-
· exists L
68-
· exists L
60+
case mp => cases h with | case L t₁_lc h₂ h₃ => exact ⟨t₁_lc, ⟨L, h₂⟩, ⟨L, h₃⟩⟩
6961
case mpr =>
7062
obtain ⟨_, ⟨_, _⟩, ⟨_, _⟩⟩ := h
71-
apply LC.case (free_union Var) <;> grind
63+
grind [LC.case <| free_union Var]
7264

7365
variable [HasFresh Var]
7466

7567
/-- Opening a body preserves local closure. -/
7668
@[scoped grind <=]
7769
lemma open_tm_body (body : t₁.body) (lc : t₂.LC) : (t₁ ^ᵗᵗ t₂).LC := by
7870
cases body
79-
have := fresh_exists <| free_union [fv_tm] Var
80-
grind [subst_tm_lc, open_tm_subst_tm_intro]
71+
grind [fresh_exists <| free_union [fv_tm] Var, subst_tm_lc, open_tm_subst_tm_intro]
8172

8273
end
8374

@@ -111,8 +102,7 @@ inductive Red : Term Var → Term Var → Prop
111102

112103
@[grind _=_]
113104
lemma rs_eq {t t' : Term Var} : t ⭢βᵛ t' ↔ Red t t' := by
114-
have : (@rs Var).Red = Red := by rfl
115-
simp_all
105+
rfl
116106

117107
variable [HasFresh Var] [DecidableEq Var] in
118108
/-- Terms of a reduction are locally closed. -/
@@ -122,8 +112,9 @@ lemma Red.lc {t t' : Term Var} (red : t ⭢βᵛ t') : t.LC ∧ t'.LC := by
122112
split_ands
123113
· grind
124114
· cases lc
125-
have := fresh_exists <| free_union [fv_tm, fv_ty] Var
126-
grind [subst_tm_lc, subst_ty_lc, open_tm_subst_tm_intro, open_ty_subst_ty_intro]
115+
grind [
116+
fresh_exists <| free_union [fv_tm, fv_ty] Var, subst_tm_lc,
117+
subst_ty_lc, open_tm_subst_tm_intro, open_ty_subst_ty_intro]
127118
all_goals grind
128119

129120
end Term

Cslib/Languages/LambdaCalculus/LocallyNameless/Fsub/Safety.lean

Lines changed: 5 additions & 9 deletions
Original file line numberDiff line numberDiff line change
@@ -42,36 +42,32 @@ lemma Typing.preservation (der : Typing Γ t τ) (step : t ⭢βᵛ t') : Typing
4242
case abs der _ _ =>
4343
have sub : Sub Γ (σ.arrow τ) (σ.arrow τ) := by grind [Sub.refl]
4444
have ⟨_, _, ⟨_, _⟩⟩ := der.abs_inv sub
45-
have ⟨_, _⟩ := fresh_exists <| free_union [fv_tm] Var
46-
grind [open_tm_subst_tm_intro, subst_tm, Sub.weaken]
45+
grind [fresh_exists <| free_union [fv_tm] Var, open_tm_subst_tm_intro, subst_tm, Sub.weaken]
4746
case tapp Γ _ σ τ σ' _ _ _ =>
4847
cases step
4948
case tabs der _ _ =>
5049
have sub : Sub Γ (σ.all τ) (σ.all τ) := by grind [Sub.refl]
5150
have ⟨_, _, ⟨_, _⟩⟩ := der.tabs_inv sub
5251
have ⟨X, _⟩ := fresh_exists <| free_union [Ty.fv, fv_ty] Var
53-
have : Γ = (Context.map_val (·[X:=σ']) []) ++ Γ := by simp
52+
have : Γ = (Context.map_val (·[X:=σ']) []) ++ Γ := by grind
5453
rw [open_ty_subst_ty_intro (X := X), open_subst_intro (X := X)] <;> grind [subst_ty]
5554
case tapp => grind
5655
case let' Γ _ _ _ _ L der _ ih₁ _ =>
5756
cases step
5857
case let_bind red₁ _ => apply Typing.let' L (ih₁ red₁); grind
5958
case let_body =>
60-
have ⟨x, _⟩ := fresh_exists <| free_union [fv_tm] Var
61-
grind [open_tm_subst_tm_intro, subst_tm]
59+
grind [fresh_exists <| free_union [fv_tm] Var, open_tm_subst_tm_intro, subst_tm]
6260
case case Γ _ σ τ _ _ _ L _ _ _ ih₁ _ _ =>
6361
have sub : Sub Γ (σ.sum τ) (σ.sum τ) := by grind [Sub.refl]
6462
have : Γ = [] ++ Γ := by rfl
6563
cases step
6664
case «case» red₁ _ _ => apply Typing.case L (ih₁ red₁) <;> grind
6765
case case_inl der _ _ =>
6866
have ⟨_, ⟨_, _⟩⟩ := der.inl_inv sub
69-
have ⟨x, _⟩ := fresh_exists <| free_union [fv_tm] Var
70-
grind [open_tm_subst_tm_intro, subst_tm]
67+
grind [fresh_exists <| free_union [fv_tm] Var, open_tm_subst_tm_intro, subst_tm]
7168
case case_inr der _ _ =>
7269
have ⟨_, ⟨_, _⟩⟩ := der.inr_inv sub
73-
have ⟨x, _⟩ := fresh_exists <| free_union [fv_tm] Var
74-
grind [open_tm_subst_tm_intro, subst_tm]
70+
grind [fresh_exists <| free_union [fv_tm] Var, open_tm_subst_tm_intro, subst_tm]
7571
all_goals grind [cases Red]
7672

7773
/-- Any typable term either has a reduction step or is a value. -/

Cslib/Languages/LambdaCalculus/LocallyNameless/Fsub/Subtype.lean

Lines changed: 7 additions & 9 deletions
Original file line numberDiff line numberDiff line change
@@ -55,15 +55,13 @@ variable {Γ Δ Θ : Env Var} {σ τ δ : Ty Var}
5555
@[grind →]
5656
lemma wf (Γ : Env Var) (σ σ' : Ty Var) (sub : Sub Γ σ σ') : Γ.Wf ∧ σ.Wf Γ ∧ σ'.Wf Γ := by
5757
induction sub with
58-
| all =>
59-
refine ⟨by grind, ?_, ?_⟩ <;>
60-
apply Wf.all (free_union Var) <;> grind [Wf.narrow_cons, cases Env.Wf, cases LC]
58+
| all => grind [Wf.all (free_union Var), Wf.narrow_cons, cases Env.Wf, cases LC]
6159
| _ => grind
6260

6361
/-- Subtypes are reflexive when well-formed. -/
6462
lemma refl (wf_Γ : Γ.Wf) (wf_σ : σ.Wf Γ) : Sub Γ σ σ := by
6563
induction wf_σ with
66-
| all => apply all (free_union [Context.dom] Var) <;> grind
64+
| all => grind [all (free_union [Context.dom] Var)]
6765
| _ => grind
6866

6967
/-- Weakening of subtypes. -/
@@ -125,7 +123,7 @@ lemma trans : Sub Γ σ δ → Sub Γ δ τ → Sub Γ σ τ := by
125123
cases eq
126124
cases sub₂
127125
case refl.top Γ σ'' τ'' _ _ _ _ _ _ _ =>
128-
have : Sub Γ (σ''.all τ'') (σ'.all τ') := by apply all (free_union Var) <;> grind
126+
have : Sub Γ (σ''.all τ'') (σ'.all τ') := by grind [all <| free_union Var]
129127
grind
130128
case refl.all Γ _ _ _ _ _ σ _ _ _ _ _ _ =>
131129
apply all (free_union Var)
@@ -141,7 +139,7 @@ instance (Γ : Env Var) : Trans (Sub Γ) (Sub Γ) (Sub Γ) :=
141139
/-- Narrowing of subtypes. -/
142140
lemma narrow (sub_δ : Sub Δ δ δ') (sub_narrow : Sub (Γ ++ ⟨X, Binding.sub δ'⟩ :: Δ) σ τ) :
143141
Sub (Γ ++ ⟨X, Binding.sub δ⟩ :: Δ) σ τ := by
144-
apply narrow_aux (δ := δ') <;> grind
142+
grind [narrow_aux (δ := δ')]
145143

146144
variable [HasFresh Var] in
147145
/-- Subtyping of substitutions. -/
@@ -164,9 +162,9 @@ lemma map_subst (sub₁ : Sub (Γ ++ ⟨X, Binding.sub δ'⟩ :: Δ) σ τ) (sub
164162
/-- Strengthening of subtypes. -/
165163
lemma strengthen (sub : Sub (Γ ++ ⟨X, Binding.ty δ⟩ :: Δ) σ τ) : Sub (Γ ++ Δ) σ τ := by
166164
generalize eq : Γ ++ ⟨X, Binding.ty δ⟩ :: Δ = Θ at sub
167-
induction sub generalizing Γ
168-
case all => apply Sub.all (free_union Var) <;> grind
169-
all_goals grind [to_ok, Wf.strengthen, Env.Wf.strengthen]
165+
induction sub generalizing Γ with
166+
| all => grind [Sub.all (free_union Var)]
167+
| _ => grind [to_ok, Wf.strengthen, Env.Wf.strengthen]
170168

171169
end Sub
172170

Cslib/Languages/LambdaCalculus/LocallyNameless/Fsub/Typing.lean

Lines changed: 15 additions & 24 deletions
Original file line numberDiff line numberDiff line change
@@ -65,12 +65,16 @@ attribute [grind .] Typing.var Typing.app Typing.tapp Typing.sub Typing.inl Typi
6565
/-- Typings have well-formed contexts and types. -/
6666
@[grind →]
6767
lemma wf {Γ : Env Var} {t : Term Var} {τ : Ty Var} (der : Typing Γ t τ) : Γ.Wf ∧ t.LC ∧ τ.Wf Γ := by
68-
induction der <;> let L := free_union Var <;> have := fresh_exists L
69-
case tabs => refine ⟨?_, LC.tabs L ?_ ?_, Ty.Wf.all L ?_ ?_⟩ <;> grind [cases Env.Wf]
70-
case abs => refine ⟨?_, LC.abs L ?_ ?_, ?_⟩ <;> grind [Wf.strengthen, cases Env.Wf]
71-
case let' => refine ⟨?_, LC.let' L ?_ ?_, ?_⟩ <;> grind [Ty.Wf.strengthen]
68+
induction der <;> let L := free_union Var <;> have ⟨x, nmem⟩ := fresh_exists L
69+
case tabs ih =>
70+
cases (ih x (by grind)).left
71+
grind [LC.tabs L, Ty.Wf.all L]
72+
case abs ih =>
73+
cases (ih x (by grind)).left
74+
grind [LC.abs L, Wf.strengthen]
75+
case let' => grind [LC.let' L, Ty.Wf.strengthen]
7276
case case => refine ⟨?_, LC.case L ?_ ?_ ?_, ?_⟩ <;> grind [Ty.Wf.strengthen]
73-
all_goals grind [of_bind_ty, open_lc, cases Env.Wf, cases Ty.Wf]
77+
all_goals grind [of_bind_ty, open_lc, cases Ty.Wf]
7478

7579
/-- Weakening of typings. -/
7680
lemma weaken (der : Typing (Γ ++ Δ) t τ) (wf : (Γ ++ Θ ++ Δ).Wf) :
@@ -89,8 +93,7 @@ lemma weaken_head (der : Typing Δ t τ) (wf : (Γ ++ Δ).Wf) :
8993
Typing (Γ ++ Δ) t τ := by
9094
have eq : Δ = [] ++ Δ := by rfl
9195
rw [eq] at der
92-
have := Typing.weaken der wf
93-
grind
96+
grind [Typing.weaken der wf]
9497

9598
/-- Narrowing of typings. -/
9699
lemma narrow (sub : Sub Δ δ δ') (der : Typing (Γ ++ ⟨X, Binding.sub δ'⟩ :: Δ) t τ) :
@@ -121,15 +124,9 @@ lemma subst_tm (der : Typing (Γ ++ ⟨X, .ty σ⟩ :: Δ) t τ) (der_sub : Typi
121124
-/
122125
grind [→ List.mem_dlookup, weaken_head, Env.Wf.strengthen, -append_assoc]
123126
· grind [Env.Wf.strengthen, => List.perm_dlookup]
124-
case abs =>
125-
apply abs (free_union Var)
126-
grind [open_tm_subst_tm_var]
127-
case tabs =>
128-
apply tabs (free_union Var)
129-
grind [open_ty_subst_tm_var]
130-
case let' der _ =>
131-
apply let' (free_union Var) (der eq)
132-
grind [open_tm_subst_tm_var]
127+
case abs => grind [abs (free_union Var), open_tm_subst_tm_var]
128+
case tabs => grind [tabs (free_union Var), open_ty_subst_tm_var]
129+
case let' der _ => grind [let' (free_union Var) (der eq), open_tm_subst_tm_var]
133130
case case der _ _ =>
134131
apply case (free_union Var) (der eq) <;> grind [open_tm_subst_tm_var]
135132
all_goals grind [Env.Wf.strengthen, Ty.Wf.strengthen, Sub.strengthen]
@@ -141,16 +138,10 @@ lemma subst_ty (der : Typing (Γ ++ ⟨X, Binding.sub δ'⟩ :: Δ) t τ) (sub :
141138
induction der generalizing Γ X
142139
case var σ _ X' _ mem =>
143140
have := map_subst_nmem Δ X δ
144-
have : Γ ++ ⟨X, .sub δ'⟩ :: Δ ~ ⟨X, .sub δ'⟩ :: (Γ ++ Δ) := perm_middle
145-
have : .ty σ ∈ dlookup X' (⟨X, .sub δ'⟩ :: (Γ ++ Δ)) := by grind [perm_dlookup]
146141
have := @map_val_mem Var (f := ((·[X:=δ]) : Binding Var → Binding Var))
147142
grind [Env.Wf.map_subst, → notMem_keys_of_nodupKeys_cons]
148-
case abs =>
149-
apply abs (free_union [Ty.fv] Var)
150-
grind [Ty.subst_fresh, open_tm_subst_ty_var]
151-
case tabs =>
152-
apply tabs (free_union Var)
153-
grind [open_ty_subst_ty_var, open_subst_var]
143+
case abs => grind [abs (free_union [Ty.fv] Var), Ty.subst_fresh, open_tm_subst_ty_var]
144+
case tabs => grind [tabs (free_union Var), open_ty_subst_ty_var, open_subst_var]
154145
case let' der _ =>
155146
apply let' (free_union Var) (der eq)
156147
grind [open_tm_subst_ty_var]

Cslib/Languages/LambdaCalculus/LocallyNameless/Fsub/WellFormed.lean

Lines changed: 8 additions & 13 deletions
Original file line numberDiff line numberDiff line change
@@ -68,13 +68,13 @@ open scoped Env.Wf
6868
@[grind →]
6969
theorem lc (wf : σ.Wf Γ) : σ.LC := by
7070
induction wf with
71-
| all => apply LC.all (free_union Var) <;> grind
71+
| all => grind [LC.all (free_union Var)]
7272
| _ => grind
7373

7474
/-- A type remains well-formed under context permutation. -/
7575
theorem perm_env (wf : σ.Wf Γ) (perm : Γ ~ Δ) (ok_Γ : Γ✓) (ok_Δ : Δ✓) : σ.Wf Δ := by
7676
induction wf generalizing Δ with
77-
| all => apply all (free_union [dom] Var) <;> grind [Perm.cons, nodupKeys_cons]
77+
| all => grind [all <| free_union [dom] Var, Perm.cons, nodupKeys_cons]
7878
| _ => grind [perm_dlookup]
7979

8080
/-- A type remains well-formed under context weakening (in the middle). -/
@@ -109,14 +109,13 @@ lemma narrow (wf : σ.Wf (Γ ++ ⟨X, Binding.sub τ⟩ :: Δ)) (ok : (Γ ++ ⟨
109109

110110
lemma narrow_cons (wf : σ.Wf (⟨X, Binding.sub τ⟩ :: Δ)) (ok : (⟨X, Binding.sub τ'⟩ :: Δ)✓) :
111111
σ.Wf (⟨X, Binding.sub τ'⟩ :: Δ) := by
112-
rw [←List.nil_append (⟨X, sub τ'⟩ :: Δ)]
113-
grind [narrow]
112+
grind [List.nil_append (⟨X, sub τ'⟩ :: Δ), narrow]
114113

115114
/-- A type remains well-formed under context strengthening. -/
116115
lemma strengthen (wf : σ.Wf (Γ ++ ⟨X, Binding.ty τ⟩ :: Δ)) : σ.Wf (Γ ++ Δ) := by
117116
generalize eq : Γ ++ ⟨X, Binding.ty τ⟩ :: Δ = Θ at wf
118117
induction wf generalizing Γ with
119-
| all => apply all (free_union [Context.dom] Var) <;> grind
118+
| all => grind [all <| free_union [Context.dom] Var]
120119
| _ => grind
121120

122121
variable [HasFresh Var] in
@@ -125,13 +124,9 @@ lemma map_subst (wf_σ : σ.Wf (Γ ++ ⟨X, Binding.sub τ⟩ :: Δ)) (wf_τ' :
125124
(ok : (Γ.map_val (·[X:=τ']) ++ Δ)✓) : σ[X:=τ'].Wf <| Γ.map_val (·[X:=τ']) ++ Δ := by
126125
have := @map_val_mem Var (Binding Var)
127126
generalize eq : Γ ++ ⟨X, Binding.sub τ⟩ :: Δ = Θ at wf_σ
128-
induction wf_σ generalizing Γ τ'
129-
case all γ _ _ _ _ _ _ =>
130-
subst eq
131-
apply all (free_union [dom] Var)
132-
· grind
133-
· grind [open_subst_var]
134-
all_goals grind [weaken_head]
127+
induction wf_σ generalizing Γ τ' with
128+
| all => apply all (free_union [dom] Var) <;> grind [open_subst_var]
129+
| _ => grind [weaken_head]
135130

136131
variable [HasFresh Var] in
137132
/-- A type remains well-formed under opening (to a well-formed type). -/
@@ -159,7 +154,7 @@ variable [HasFresh Var] in
159154
/-- A variable not appearing in a context does not appear in its well-formed types. -/
160155
lemma nmem_fv {σ : Ty Var} (wf : σ.Wf Γ) (nmem : X ∉ Γ.dom) : X ∉ σ.fv := by
161156
induction wf with
162-
| all => have := fresh_exists <| free_union [dom] Var; grind [nmem_fv_open, openRec_lc]
157+
| all => grind [fresh_exists <| free_union [dom] Var, nmem_fv_open, openRec_lc]
163158
| _ => grind [dlookup_isSome]
164159

165160
end Ty.Wf

0 commit comments

Comments
 (0)