Skip to content

Commit 3b47a7b

Browse files
m-owchenson2018
andauthored
refactor: define FullBeta using Xi (#455)
I have tested this branch and can confirm that this refactor provides the necessary for proving $\beta \eta$-confluence. --------- Co-authored-by: Chris Henson <chrishenson.net@gmail.com>
1 parent 74388a7 commit 3b47a7b

7 files changed

Lines changed: 52 additions & 44 deletions

File tree

Cslib/Languages/LambdaCalculus/LocallyNameless/Stlc/Basic.lean

Lines changed: 1 addition & 0 deletions
Original file line numberDiff line numberDiff line change
@@ -88,6 +88,7 @@ lemma weaken (der : Γ ⊢ t ∶ τ) (ok : (Γ ++ Δ)✓) : Γ ++ Δ ⊢ t ∶
8888

8989
omit [DecidableEq Var] in
9090
/-- Typing derivations exist only for locally closed terms. -/
91+
@[scoped grind →]
9192
lemma lc (der : Γ ⊢ t ∶ τ) : t.LC := by
9293
induction der <;> constructor
9394
case abs ih => exact ih

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

Lines changed: 9 additions & 10 deletions
Original file line numberDiff line numberDiff line change
@@ -67,9 +67,9 @@ set_option linter.unusedDecidableInType false in
6767
theorem preservation (der : Γ ⊢ t ∶ τ) (step : t ⭢βᶠ t') : Γ ⊢ t' ∶ τ := by
6868
induction der generalizing t' <;> cases step
6969
case abs.abs xs _ _ _ xs' _ => apply Typing.abs (free_union Var); grind
70-
case app.beta der _ _ _ der_l _ _ =>
71-
-- TODO: this is a regression from aesop, where `preservation_open` was a forward rule
72-
cases der_l with | abs _ cofin => simp [preservation_open cofin der]
70+
case app.base h der _ _ der_l =>
71+
cases der_l
72+
cases h with | abs _ cofin => exact preservation_open cofin der
7373
all_goals grind
7474

7575
open scoped Term in
@@ -88,15 +88,14 @@ theorem progress {t : Term Var} {τ : Ty Base} (ht : [] ⊢ t ∶ τ) : t.Value
8888
case app Γ M σ τ N der_l der_r ih_l ih_r =>
8989
simp only [eq, forall_const] at *
9090
right
91-
cases ih_l
91+
cases ih_l with
9292
-- if the lhs is a value, beta reduce the application
93-
next val =>
94-
cases val
95-
next M M_abs_lc => exact ⟨M ^ N, Term.FullBeta.beta M_abs_lc der_r.lc⟩
93+
| inl val => cases val with | abs M _ => use M ^ N, by grind
9694
-- otherwise, propogate the step to the lhs of the application
97-
next step =>
98-
obtain ⟨M', stepM⟩ := step
99-
exact ⟨M'.app N, Term.FullBeta.appR der_r.lc stepM⟩
95+
| inr step =>
96+
obtain ⟨M', _⟩ := step
97+
use M'.app N
98+
grind
10099

101100
end FullBeta
102101

Cslib/Languages/LambdaCalculus/LocallyNameless/Untyped/FullBeta.lean

Lines changed: 14 additions & 16 deletions
Original file line numberDiff line numberDiff line change
@@ -8,6 +8,7 @@ module
88

99
public import Cslib.Foundations.Data.Relation
1010
public import Cslib.Languages.LambdaCalculus.LocallyNameless.Untyped.Properties
11+
public import Cslib.Languages.LambdaCalculus.LocallyNameless.Untyped.Congruence
1112

1213
public section
1314

@@ -32,28 +33,25 @@ variable {Var : Type u}
3233
namespace LambdaCalculus.LocallyNameless.Untyped.Term
3334

3435
/-- A single β-reduction step. -/
35-
@[reduction_sys "βᶠ"]
36-
inductive FullBeta : Term Var → Term Var → Prop
36+
@[scoped grind]
37+
inductive Beta : Term Var → Term Var → Prop
3738
/-- Reduce an application to a lambda term. -/
38-
| beta : LC (abs M)→ LC N → FullBeta (app (abs M) N) (M ^ N)
39-
/-- Left congruence rule for application. -/
40-
| appL: LC Z → FullBeta M N → FullBeta (app Z M) (app Z N)
41-
/-- Right congruence rule for application. -/
42-
| appR : LC Z → FullBeta M N → FullBeta (app M Z) (app N Z)
43-
/-- Congruence rule for lambda terms. -/
44-
| abs (xs : Finset Var) : (∀ x ∉ xs, FullBeta (M ^ fvar x) (N ^ fvar x)) → FullBeta (abs M) (abs N)
39+
| beta : LC (abs M)→ LC N → Beta (app (abs M) N) (M ^ N)
4540

46-
namespace FullBeta
41+
/-- Full β-reduction. -/
42+
@[reduction_sys "βᶠ"]
43+
abbrev FullBeta : Term Var → Term Var → Prop := Xi Beta
4744

48-
attribute [scoped grind .] appL appR
45+
namespace FullBeta
4946

5047
variable {M M' N N' : Term Var}
5148

5249
/-- The left side of a reduction is locally closed. -/
5350
@[scoped grind →]
5451
lemma step_lc_l (step : M ⭢βᶠ M') : LC M := by
55-
induction step <;> constructor
56-
all_goals assumption
52+
induction step with
53+
| abs => constructor; assumption
54+
| _ => grind
5755

5856
/-- Left congruence rule for application in multiple reduction. -/
5957
@[scoped grind ←]
@@ -81,8 +79,8 @@ lemma steps_lc_or_rfl {M M' : Term Var} (redex : M ↠βᶠ M') : (LC M ∧ LC M
8179
lemma redex_subst_cong_lc (s s' t : Term Var) (x : Var) (step : s ⭢βᶠ s') (h_lc : LC t) :
8280
s [ x := t ] ⭢βᶠ s' [ x := t ] := by
8381
induction step with
84-
| beta => grind [subst_open, beta]
85-
| abs => grind [abs <| free_union Var]
82+
| base => grind [subst_open]
83+
| abs => grind [Xi.abs <| free_union Var]
8684
| _ => grind
8785

8886
/-- Substitution respects a single reduction step of a free variable. -/
@@ -92,7 +90,7 @@ lemma redex_subst_cong (s s' : Term Var) (x y : Var) (step : s ⭢βᶠ s') :
9290

9391
/-- Abstracting then closing preserves a single reduction. -/
9492
lemma step_abs_close {x : Var} (step : M ⭢βᶠ M') : M⟦0 ↜ x⟧.abs ⭢βᶠ M'⟦0 ↜ x⟧.abs := by
95-
grind [abs ∅, redex_subst_cong]
93+
grind [Xi.abs ∅, redex_subst_cong]
9694

9795
/-- Abstracting then closing preserves multiple reductions. -/
9896
lemma redex_abs_close {x : Var} (step : M ↠βᶠ M') : (M⟦0 ↜ x⟧.abs ↠βᶠ M'⟦0 ↜ x⟧.abs) := by

Cslib/Languages/LambdaCalculus/LocallyNameless/Untyped/FullBetaConfluence.lean

Lines changed: 8 additions & 5 deletions
Original file line numberDiff line numberDiff line change
@@ -74,10 +74,13 @@ lemma para_lc_r (step : M ⭢ₚ N) : LC N := by
7474
omit [HasFresh Var] [DecidableEq Var] in
7575
/-- A single β-reduction implies a single parallel reduction. -/
7676
lemma step_to_para (step : M ⭢βᶠ N) : M ⭢ₚ N := by
77-
induction step
78-
case beta _ abs_lc _ => cases abs_lc with | abs xs _ => apply Parallel.beta xs <;> grind
79-
case abs xs _ _ => apply Parallel.abs xs; grind
80-
all_goals grind
77+
induction step with
78+
| base h =>
79+
cases h with | beta abs_lc _ =>
80+
cases abs_lc with | abs xs _ =>
81+
apply Parallel.beta xs <;> grind
82+
| abs xs _ _ => apply Parallel.abs xs; grind
83+
| _ => grind
8184

8285
open FullBeta in
8386
/-- A single parallel reduction implies a multiple β-reduction. -/
@@ -99,7 +102,7 @@ lemma para_to_redex (para : M ⭢ₚ N) : M ↠βᶠ N := by
99102
m'.abs.app n :=
100103
redex_app_l_cong (redex_abs_cong xs (fun _ mem ↦ redex_ih _ mem)) (para_lc_l para_n)
101104
_ ↠βᶠ m'.abs.app n' := by grind
102-
_ ⭢βᶠ m' ^ n' := beta m'_abs_lc (by grind)
105+
_ ⭢βᶠ m' ^ n' := by grind
103106

104107
/-- Multiple parallel reduction is equivalent to multiple β-reduction. -/
105108
theorem parachain_iff_redex : M ↠ₚ N ↔ M ↠βᶠ N := by

Cslib/Languages/LambdaCalculus/LocallyNameless/Untyped/MultiApp.lean

Lines changed: 5 additions & 5 deletions
Original file line numberDiff line numberDiff line change
@@ -55,7 +55,7 @@ lemma multiApp_lc : LC (M.multiApp Ns) ↔ LC M ∧ (∀ N ∈ Ns, LC N) := by
5555
@[scoped grind ←]
5656
lemma step_multiApp_l (steps : M ⭢βᶠ M') (lc_Ns : ∀ N ∈ Ns, LC N) :
5757
M.multiApp Ns ⭢βᶠ M'.multiApp Ns := by
58-
induction Ns <;> grind [FullBeta.appR]
58+
induction Ns <;> grind
5959

6060
/-- Congruence lemma for multi reduction of the left most term of a multi-application -/
6161
lemma steps_multiApp_l (steps : M ↠βᶠ M') (lc_Ns : ∀ N ∈ Ns, LC N) :
@@ -65,11 +65,11 @@ lemma steps_multiApp_l (steps : M ↠βᶠ M') (lc_Ns : ∀ N ∈ Ns, LC N) :
6565
/-- Congruence lemma for single reduction of one of the arguments of a multi-application -/
6666
@[scoped grind ←]
6767
lemma step_multiApp_r (steps : Ns ⭢lβᶠ Ns') (lc_M : LC M) : M.multiApp Ns ⭢βᶠ M.multiApp Ns' := by
68-
induction steps <;> grind [FullBeta.appL, FullBeta.appR]
68+
induction steps <;> grind
6969

7070
/-- Congruence lemma for multiple reduction of one of the arguments of a multi-application -/
7171
lemma steps_multiApp_r (steps : Ns ↠lβᶠ Ns') (lc_M : LC M) : M.multiApp Ns ↠βᶠ M.multiApp Ns' := by
72-
induction steps <;> grind [FullBeta.appL, FullBeta.appR]
72+
induction steps <;> grind
7373

7474
/-- If a term (λ M) N P_1 ... P_n reduces in a single step to Q, then
7575
Q must be one of the following forms:
@@ -85,13 +85,13 @@ lemma invert_abs_multiApp_st {Ps} {M N Q : Term Var}
8585
(∃ Ps', Ps ⭢lβᶠ Ps' ∧ Q = multiApp (M.abs.app N) Ps') ∨
8686
(Q = multiApp (M ^ N) Ps) := by
8787
induction Ps generalizing M N Q with
88-
| nil => grind [cases FullBeta]
88+
| nil => grind [cases Xi]
8989
| cons P Ps ih =>
9090
generalize Heq : (M.abs.app N).multiApp Ps = Q'
9191
have : ∀ P', Q'.app P' = (M.abs.app N).multiApp (P' :: Ps) := by grind
9292
rw [multiApp, Heq] at h_red
9393
cases h_red with
94-
| beta => cases Ps <;> contradiction
94+
| base => cases Ps <;> grind
9595
| appR => grind [→ ListFullBeta.cons]
9696
| appL => grind
9797

Cslib/Languages/LambdaCalculus/LocallyNameless/Untyped/StrongNorm.lean

Lines changed: 14 additions & 8 deletions
Original file line numberDiff line numberDiff line change
@@ -43,7 +43,7 @@ lemma sn_steps (t_st_t' : t ↠βᶠ t') (sn_t : SN t) : SN t' := by
4343

4444
/-- Free variables are strongly normalizing. -/
4545
lemma sn_fvar {x : Var} : SN (fvar x) := by
46-
grind [cases FullBeta]
46+
grind only [cases Xi, cases Beta, SN]
4747

4848
/-- An application is strongly normalizing if the left and right terms are strongly normalizing,
4949
as well as all possible future top level abstraction application beta reductions -/
@@ -56,7 +56,7 @@ lemma sn_app (t s : Term Var) (sn_t : SN t) (sn_s : SN s)
5656
constructor
5757
intro u hstep
5858
cases hstep with
59-
| beta _ _ => grind
59+
| base h => cases h; grind
6060
| appL _ h_s_red => apply ih_s _ h_s_red
6161
grind [Relation.ReflTransGen.head]
6262
| appR _ h_t_red => apply ih_t _ h_t_red _ (SN.sn s hs)
@@ -91,7 +91,7 @@ inductive Neutral : Term Var → Prop
9191

9292
/-- Neutral terms only reduce to other neutral terms in a single step -/
9393
lemma neutral_step (Hneut : Neutral t) (Hstep : t ⭢βᶠ t') : Neutral t' := by
94-
induction Hneut generalizing t' with grind [cases FullBeta, sn_step]
94+
induction Hneut generalizing t' with grind only [Neutral, cases Xi, sn_step]
9595

9696
/-- Neutral terms only reduce to other neutral terms in multiple steps -/
9797
lemma neutral_steps (Hneut : Neutral t) (Hsteps : t ↠βᶠ t') : Neutral t' := by
@@ -101,7 +101,7 @@ lemma neutral_steps (Hneut : Neutral t) (Hsteps : t ↠βᶠ t') : Neutral t' :=
101101
lemma sn_neutral (Hneut : Neutral t) : SN t := by
102102
induction Hneut with
103103
| app => grind [→ neutral_steps, sn_app]
104-
| _ => grind [cases FullBeta]
104+
| _ => grind only [SN, cases Xi]
105105

106106
/-- A lambda abstraction is strongly normalizing if its body is strongly normalizing. -/
107107
lemma sn_abs [DecidableEq Var] [HasFresh Var] {M N : Term Var} (sn_MN : SN (M ^ N)) (lc_N : LC N) :
@@ -111,7 +111,9 @@ lemma sn_abs [DecidableEq Var] [HasFresh Var] {M N : Term Var} (sn_MN : SN (M ^
111111
| sn =>
112112
constructor
113113
intro _ h_step
114-
cases h_step with | abs _ H => grind [step_open_cong_l _ _ _ _ H]
114+
cases h_step with
115+
| abs _ H => grind [step_open_cong_l _ _ _ _ H]
116+
| base _ => contradiction
115117

116118
/-- A term of the form λ M N P_1 … P_n is strongly normalizing if
117119
1. N is strongly normalizing,
@@ -141,12 +143,16 @@ lemma sn_abs_app_multiApp [DecidableEq Var] [HasFresh Var] {Ps} {M N : Term Var}
141143
· apply steps_multiApp_l
142144
· apply steps_open_cong_abs M M' N N' <;> grind [open_abs_lc]
143145
· grind [multiApp_steps_lc]
144-
apply sn_steps
146+
refine sn_steps ?_ sn_MNPs
145147
· calc ((M ^ N).multiApp Ps).app P
146148
_ ↠βᶠ ((M ^ N).multiApp Ps).app P' := by grind
147149
_ ↠βᶠ Q'.abs.app P' := redex_app_l_cong (.trans innerSteps h_st2) (by grind)
148-
_ ↠βᶠ Q' ^ P' := by grind [beta]
149-
· grind
150+
_ ↠βᶠ Q' ^ P' := by
151+
rw [Relation.reflTransGen_iff_eq_or_transGen] at ⊢ innerSteps h_st2
152+
right
153+
cases lc_MNPs
154+
refine Relation.TransGen.single (Xi.base (Beta.beta ?_ ?_))
155+
all_goals grind only [→ step_lc_r]
150156

151157
end LambdaCalculus.LocallyNameless.Untyped.Term
152158

CslibTests/GrindLint.lean

Lines changed: 1 addition & 0 deletions
Original file line numberDiff line numberDiff line change
@@ -78,6 +78,7 @@ open_scoped_all Cslib
7878
#grind_lint skip Cslib.LambdaCalculus.LocallyNameless.Fsub.Env.Wf.ty
7979
#grind_lint skip Cslib.Logic.HML.bisimulation_satisfies
8080
#grind_lint skip Cslib.Logic.HML.Satisfies.diamond
81+
#grind_lint skip Cslib.LambdaCalculus.LocallyNameless.Untyped.Term.step_multiApp_l
8182

8283
#guard_msgs in
8384
#grind_lint check (min := 20) in Cslib

0 commit comments

Comments
 (0)