Skip to content
Merged
Show file tree
Hide file tree
Changes from 10 commits
Commits
Show all changes
23 commits
Select commit Hold shift + click to select a range
3c41d95
changes to MultiSubst.lean
WegmannDavid Mar 6, 2026
055bd9e
removed files that do not belong in this pull request
WegmannDavid Mar 6, 2026
c245bbc
removed files that do not belong in this pull request
WegmannDavid Mar 6, 2026
c9c2236
applied the same style suggestions from the previous pull request
WegmannDavid Mar 7, 2026
f21151b
removed accidental reversion in LcAt
WegmannDavid Mar 7, 2026
4e09785
removed accidental reversion in FullBeta
WegmannDavid Mar 7, 2026
58aae95
removed accidental reversion in Properties
WegmannDavid Mar 7, 2026
56dba11
instructed linter to ignore warnings
WegmannDavid Mar 7, 2026
83b6d04
removed one false too much
WegmannDavid Mar 7, 2026
107a419
ran lake exe mk_all
WegmannDavid Mar 7, 2026
85a6038
implemented some of the requested changed
WegmannDavid Mar 7, 2026
bedab8a
renamed multiApp_full_beta to list_full_beta and added l to notation …
WegmannDavid Mar 7, 2026
44683a1
added section variables to reduce hypothesis clutter
WegmannDavid Mar 7, 2026
06885f9
some style work
chenson2018 Mar 8, 2026
a92f85e
rm extra params to grind
chenson2018 Mar 8, 2026
a4ee71b
golf invert_abs_multiApp_mst
chenson2018 Mar 8, 2026
a03d127
golf invert_abs_multiApp_st
chenson2018 Mar 8, 2026
eb1e9eb
grind_lint
chenson2018 Mar 8, 2026
6de1a4d
added docstring
WegmannDavid Mar 8, 2026
9a5ccef
added docstrings to constructors of ListFullBeta
WegmannDavid Mar 8, 2026
f2b52e9
changed /- to /-- for docstrings to work
WegmannDavid Mar 8, 2026
1d63423
removed comma in docstring
WegmannDavid Mar 8, 2026
87e2024
Merge branch 'leanprover:main' into pr/MultiApp
WegmannDavid Mar 8, 2026
File filter

Filter by extension

Filter by extension

Conversations
Failed to load comments.
Loading
Jump to
Jump to file
Failed to load files.
Loading
Diff view
Diff view
1 change: 1 addition & 0 deletions Cslib.lean
Original file line number Diff line number Diff line change
Expand Up @@ -91,6 +91,7 @@ public import Cslib.Languages.LambdaCalculus.LocallyNameless.Untyped.Basic
public import Cslib.Languages.LambdaCalculus.LocallyNameless.Untyped.FullBeta
public import Cslib.Languages.LambdaCalculus.LocallyNameless.Untyped.FullBetaConfluence
public import Cslib.Languages.LambdaCalculus.LocallyNameless.Untyped.LcAt
public import Cslib.Languages.LambdaCalculus.LocallyNameless.Untyped.MultiApp
public import Cslib.Languages.LambdaCalculus.LocallyNameless.Untyped.Properties
public import Cslib.Languages.LambdaCalculus.Named.Untyped.Basic
public import Cslib.Logics.HML.Basic
Expand Down
201 changes: 201 additions & 0 deletions Cslib/Languages/LambdaCalculus/LocallyNameless/Untyped/MultiApp.lean
Original file line number Diff line number Diff line change
@@ -0,0 +1,201 @@
/-
Author: David Wegmann
Comment thread
chenson2018 marked this conversation as resolved.
Outdated
-/


module


public import Cslib.Languages.LambdaCalculus.LocallyNameless.Untyped.FullBeta

set_option linter.unusedDecidableInType false
set_option linter.unusedSectionVars false
set_option linter.unusedVariables false
Comment thread
chenson2018 marked this conversation as resolved.
Outdated

@[expose] public section

namespace Cslib

universe u

variable {Var : Type u} [DecidableEq Var] [HasFresh Var]

namespace LambdaCalculus.LocallyNameless.Untyped.Term


/-
multiApp f [x_1, x_2, ..., x_n] applies the arguments x_1, x_2, ..., x_n
to f in left-associative order, i.e. as (((f x_1) x_2) ... x_n).
Comment thread
chenson2018 marked this conversation as resolved.
Outdated
-/
@[simp]
Comment thread
chenson2018 marked this conversation as resolved.
Outdated
def multiApp (f : Term Var) (args : List (Term Var)) :=
match args with
| [] => f
| a :: as => Term.app (multiApp f as) a

/-
A list of arguments performs a single reduction step

[x_1, ..., x_i ..., x_n] ⭢βᶠ [x_1, ..., x_i', ..., x_n]

if one of the arguments performs a single step, and the rest are locally closed.
-/
@[reduction_sys "βᶠ"]
Comment thread
chenson2018 marked this conversation as resolved.
Outdated
inductive multiApp_full_beta : List (Term Var) → List (Term Var) → Prop where
| step : N ⭢βᶠ N' → (∀ N ∈ Ns, LC N) → multiApp_full_beta (N :: Ns) (N' :: Ns)
| cons : LC N → multiApp_full_beta Ns Ns' → multiApp_full_beta (N :: Ns) (N :: Ns')

attribute [scoped grind .] multiApp_full_beta.step multiApp_full_beta.cons

/- just like ordinary beta reduction, the right-hand side
of a multi-application step is locally closed -/
lemma multiApp_step_lc_r {Ns Ns' : List (Term Var)}
(step : Ns ⭢βᶠ Ns') :
(∀ N ∈ Ns', LC N) := by
Comment thread
chenson2018 marked this conversation as resolved.
Outdated
induction step <;> grind [FullBeta.step_lc_r]

/- just like ordinary beta reduction, multiple steps of a argument list preserves local closure -/
lemma multiApp_steps_lc {Ns Ns' : List (Term Var)}
(step : Ns ↠βᶠ Ns') (H : ∀ N ∈ Ns, LC N) :
(∀ N ∈ Ns', LC N) := by
induction step <;> grind [FullBeta.step_lc_r, multiApp_step_lc_r]

/- a term resulting from a multi-application is locally closed if
and only if the leftmost term and all arguments applied to it are locally closed -/
@[scoped grind ←]
lemma multiApp_lc {M : Term Var} {Ns : List (Term Var)} :
LC (M.multiApp Ns) ↔ LC M ∧ (∀ N ∈ Ns, LC N)
:= by
Comment thread
chenson2018 marked this conversation as resolved.
Outdated
constructor
· induction Ns
· case nil => grind [multiApp]
· case cons N Ns ih => intro h_lc; cases h_lc; grind
Comment thread
chenson2018 marked this conversation as resolved.
Outdated
· induction Ns <;> grind [multiApp, LC.app]

/- just like ordinary beta reduction, the left-hand side
of a multi-application step is locally closed -/
@[scoped grind ←]
lemma step_multiApp_l {M M' : Term Var} {Ns : List (Term Var)}
(steps : M ⭢βᶠ M')
(lc_Ns : ∀ N ∈ Ns, LC N) :
M.multiApp Ns ⭢βᶠ M'.multiApp Ns := by
induction Ns <;> grind [multiApp, FullBeta.appR]

/- congruence lemma for multi reduction of the left most term of a multi-application -/
@[scoped grind ←]
lemma steps_multiApp_l {M M' : Term Var} {Ns : List (Term Var)}
Comment thread
chenson2018 marked this conversation as resolved.
Outdated
(steps : M ↠βᶠ M')
(lc_Ns : ∀ N ∈ Ns, LC N) :
M.multiApp Ns ↠βᶠ M'.multiApp Ns := by
induction steps <;> grind

/- congruence lemma for single reduction of one of the arguments of a multi-application -/
@[scoped grind ←]
lemma step_multiApp_r {M : Term Var} {Ns Ns' : List (Term Var)}
(steps : Ns ⭢βᶠ Ns')
(lc_M : LC M) :
M.multiApp Ns ⭢βᶠ M.multiApp Ns' := by
induction steps <;> grind [multiApp, FullBeta.appL, FullBeta.appR]

/- congruence lemma for multiple reduction of one of the arguments of a multi-application -/
@[scoped grind ←]
lemma steps_multiApp_r {M : Term Var} {Ns Ns' : List (Term Var)}
(steps : Ns ↠βᶠ Ns')
(lc_M : LC M) :
M.multiApp Ns ↠βᶠ M.multiApp Ns' := by
induction steps <;> grind [multiApp, FullBeta.appL, FullBeta.appR]

/- if a term (λ M) N P_1 ... P_n reduces in a single step to Q, then
Q must be one of the following forms:

Q = (λ M') N P_1 ... P_n where M ⭢βᶠ M' or
Q = (λ M) N' P_1 ... P_n where N ⭢βᶠ N' or
Q = (λ M) N P_1' ... P_n' where P_i ⭢βᶠ P_i' for some i or
Q = (M ^ N) P_1 ... P_n
-/
lemma invert_abs_multiApp_st {Ps} {M N Q : Term Var}
(h_red : multiApp (M.abs.app N) Ps ⭢βᶠ Q) :
(∃ M', M.abs ⭢βᶠ Term.abs M' ∧ Q = multiApp (M'.abs.app N) Ps) ∨
(∃ N', N ⭢βᶠ N' ∧ Q = multiApp (M.abs.app N') Ps) ∨
(∃ Ps', Ps ⭢βᶠ Ps' ∧ Q = multiApp (M.abs.app N) Ps') ∨
(Q = multiApp (M ^ N) Ps) := by
Comment thread
chenson2018 marked this conversation as resolved.
induction Ps generalizing M N Q with
| nil =>
rw [multiApp] at h_red
rw [multiApp]
cases h_red
· case beta abs_lc n_lc => aesop
· case appL M N' lc_z h_red => aesop
· case appR M M' lc_z h_red =>
left
cases lc_z
· case abs M' xs h_lc =>
exists M'
constructor
· apply FullBeta.step_abs_cong
assumption
· rfl
| cons P Ps ih =>
have h_lc := (FullBeta.step_lc_l h_red)
rw [multiApp] at h_red
generalize Heq : (M.abs.app N).multiApp Ps = Q'
rw [Heq] at h_red
cases h_red
· case beta abs_lc n_lc => cases Ps <;> contradiction
· case appL Y M P' lc_z h_red =>
right; right; left
exists (P' :: Ps)
simp
grind
· case appR M Q'' h_red P_lc =>
rw [←Heq] at h_red
match (ih h_red) with
| .inl ⟨ M', st, Heq' ⟩ => aesop
| .inr (.inl ⟨ N', st, Heq' ⟩) => aesop
| .inr (.inr (.inl ⟨ Ps', st, Heq' ⟩)) =>
right; right; left
exists (P :: Ps')
simp
grind
| .inr (.inr (.inr Heq')) => aesop

/- if a term (λ M) N P_1 ... P_n reduces in multiple steps to Q, then either Q if of the form

Q = (λ M') N' P'_1 ... P'_n

or

we first reach an intermediate term of this shape,

(λ M) N P_1 ... P_n ↠βᶠ (λ M') N' P'_1 ... P'_n

then perform a beta reduction and reduce further to Q

(λ M') N' P'_1 ... P'_n ↠βᶠ M' ^ N' P'_1 ... P'_n ↠βᶠ Q

where M ↠βᶠ M' and N ↠βᶠ N' and P_i ↠βᶠ P_i' for all i,
-/
lemma invert_abs_multiApp_mst {Ps} {M N Q : Term Var}
(h_red : multiApp (M.abs.app N) Ps ↠βᶠ Q) :
∃ M' N' Ns', M.abs ↠βᶠ M'.abs ∧ N ↠βᶠ N' ∧ Ps ↠βᶠ Ns' ∧
(Q = multiApp (M'.abs.app N') Ns' ∨
(multiApp (M.abs.app N) Ps ↠βᶠ multiApp (M' ^ N') Ns' ∧
multiApp (M' ^ N') Ns' ↠βᶠ Q)) := by
induction h_red
· case refl => grind
· case tail Q' Q'' steps step ih =>
match ih with
| ⟨ M', N', Ps', st_M, st_N, st_Ps, Cases ⟩ =>
match Cases with
| .inl Heq =>
rw [Heq] at step
match (invert_abs_multiApp_st step) with
| .inl ⟨ M'', st, HeqM'' ⟩ => grind
| .inr (.inl ⟨ N', st, Heq' ⟩) => grind
| .inr (.inr (.inl ⟨ Ps', st, Heq' ⟩)) => grind
| .inr (.inr (.inr Heq')) => grind
| .inr ⟨ steps1, steps2 ⟩ => grind [Relation.ReflTransGen.single]

end LambdaCalculus.LocallyNameless.Untyped.Term

end Cslib
Loading