feat: de Bruijn Syntax for Untyped Lambda Calculus and a proof of Church-Rosser with Parallel Reduction#475
feat: de Bruijn Syntax for Untyped Lambda Calculus and a proof of Church-Rosser with Parallel Reduction#475zayn7lie wants to merge 26 commits intoleanprover:mainfrom
Conversation
chenson2018
left a comment
There was a problem hiding this comment.
Hi, thanks for your interest in contributing to CSLib! We do have Church-Rosser for locally nameless binding, but I think we are interested in having the more common de Bruijn indices representation as well.
I see there is a disclosure of AI usage, but this looks like its been mostly cleaned up pretty well, so thank you.
Below are some initial reviews about making this fit into CSLib conventions.
Thanks for notification, sorry for confusion. |
I don't understand this comment. It looks as I would expect for this binding scheme. |
Please read the header comment docs of |
|
Can you rename |
I am somehow hesitant to do that. The current |
|
I agree that we should almost always use the notation and corresponding naming, which is then based off I've started a second pass of reviews which I'll try to have complete in a few days. |
| (h₁ : ∀ {a b}, r a b → p a b) | ||
| (h₂ : ∀ {a b}, p a b → ReflTransGen r a b) : | ||
| ∀ {a b}, ReflTransGen r a b ↔ ReflTransGen p a b := by |
There was a problem hiding this comment.
Perhaps better as
| (h₁ : ∀ {a b}, r a b → p a b) | |
| (h₂ : ∀ {a b}, p a b → ReflTransGen r a b) : | |
| ∀ {a b}, ReflTransGen r a b ↔ ReflTransGen p a b := by | |
| (h₁ : r ≤ p) | |
| (h₂ : p ≤ ReflTransGen r) : | |
| ReflTransGen r = ReflTransGen p := by |
I think this was discussed on Zulip?
There was a problem hiding this comment.
Yes, this thread. I'd use the naming and shorter proof discussed there as well.
There was a problem hiding this comment.
| | Par.var t => cases em (t = n) with | ||
| | inl h => | ||
| simp_all only [sub, subst, ↓reduceIte, | ||
| decre_incre_elim, incre_par] | ||
| | inr h => cases em (t < n) with |
There was a problem hiding this comment.
I think this is better handled with obtain h | h | h := lt_trichotomy t n
| notation:max "𝕧" str => Term.var str | ||
| notation:max "λ." t => Term.abs t | ||
| infixl:77 "·" => Term.app |
There was a problem hiding this comment.
These should use @[inherit_doc]
There was a problem hiding this comment.
The application notation is also problematic, as it conflicts the core \. notation.
| /-- `subst j s t` substitutes `j` with term `s` in `t`. -/ | ||
| @[expose] public def subst (j : Nat) (s : Term) : Term → Term | ||
| | var k => if k = j then s else var k | ||
| | abs t => abs (subst (j + 1) (incre 1 0 s) t) | ||
| | app t u => app (subst j s t) (subst j s u) | ||
|
|
||
| /-- `decre i l t` decrements `i` for all free vars `≥ l + i`. | ||
| the reason using `l + i` is that it is more explicit for | ||
| free variable elimination. For example, after eliminating | ||
| `var k` for Term `t` from the most outside, `decre 1 k t` | ||
| will close the gap caused by `k` elimination. -/ | ||
| @[expose] public def decre (i : Nat) (l : Nat) : Term → Term | ||
| | var k => if l + i ≤ k then var (k - i) else var k | ||
| | abs t => abs (decre i (l + 1) t) | ||
| | app t u => app (decre i l t) (decre i l u) |
There was a problem hiding this comment.
Should this be a single operation?
There was a problem hiding this comment.
Hmm, I don't think I've ever seen it done that way before? It might be awkward not having incre and decre as inverses. I'm not sure though.
| | var : Nat → Term | ||
| | abs : Term → Term | ||
| | app : Term → Term → Term |
There was a problem hiding this comment.
Please write a docstring for each of these
There was a problem hiding this comment.
I mean put a docstring on each one, not add to the main docstring.
chenson2018
left a comment
There was a problem hiding this comment.
This is still not comprehensive, but a few more comments. The comment about squeezing terminal simp applies throughout and is one factor making proofs much longer than they need to be. Could you work on fixing this a bit?
There was a problem hiding this comment.
Let's follow the convention of naming this file Basic.lean.
| -/ | ||
|
|
||
|
|
||
| namespace Lambda |
There was a problem hiding this comment.
The namespacing should closely follow the previous lamba calculi developments. I think that would make this Cslib.LambdaCalculus.Unscoped.Untyped.
| open Term | ||
| namespace Term |
There was a problem hiding this comment.
It is redundant to both open and then enter a namespace
| open Term | |
| namespace Term | |
| namespace Term |
| infixl:77 "·" => Term.app | ||
|
|
||
| /-- `incre i l t` increments `i` for all free vars `≥ l`. -/ | ||
| @[expose] public def incre (i : Nat) (l : Nat) : Term → Term |
There was a problem hiding this comment.
As I mentioned previously, I would remove everywhere you use public and @[expose] in favor of @[expose] public section
| induction t generalizing l with | ||
| | var k => simp_all only [incre, Nat.add_zero, ite_self] | ||
| | abs t ih => simp_all only [incre] | ||
| | app t u iht ihu => simp_all only [incre] |
There was a problem hiding this comment.
These simp are terminal, so do not need to be squeezed. Personally I would just write
| induction t generalizing l with | |
| | var k => simp_all only [incre, Nat.add_zero, ite_self] | |
| | abs t ih => simp_all only [incre] | |
| | app t u iht ihu => simp_all only [incre] | |
| induction t generalizing l with grind [incre] |
| notation:max "𝕧" str => Term.var str | ||
| notation:max "λ." t => Term.abs t | ||
| infixl:77 "·" => Term.app |
There was a problem hiding this comment.
The application notation is also problematic, as it conflicts the core \. notation.
| (h₁ : ∀ {a b}, r a b → p a b) | ||
| (h₂ : ∀ {a b}, p a b → ReflTransGen r a b) : | ||
| ∀ {a b}, ReflTransGen r a b ↔ ReflTransGen p a b := by |
There was a problem hiding this comment.
Yes, this thread. I'd use the naming and shorter proof discussed there as well.
…lation`, and add `rtc_eq_of_sandwich`
…lation`, and add `rtc_eq_of_sandwich`
…multi-step closure
| (t·u) ↠β (t'·u) := by | ||
| induction h with | ||
| | refl => exact refl (t·u) | ||
| | tail hab hbc ih => exact tail ih (Beta.appL hbc) |
There was a problem hiding this comment.
| (t·u) ↠β (t'·u) := by | |
| induction h with | |
| | refl => exact refl (t·u) | |
| | tail hab hbc ih => exact tail ih (Beta.appL hbc) | |
| (t·u) ↠β (t'·u) := | |
| h.lift (· ·u) fun _ _ => .appL |
etc
| theorem app {t t' u u'} | ||
| (ht : t ↠β t') (hu : u ↠β u') : | ||
| (app t u) ↠β (app t' u') := | ||
| Relation.ReflTransGen.trans (appL ht) (appR hu) |
There was a problem hiding this comment.
perhaps:
| Relation.ReflTransGen.trans (appL ht) (appR hu) | |
| (appL ht).trans (appR hu) |
| /-- Notation typeclass for substitution, t[n := s] ≃ t.sub n s | ||
| which substitute nth variable in t with s. -/ | ||
| instance : Cslib.HasSubstitution Term Nat Term | ||
| where subst := sub |
There was a problem hiding this comment.
There's no reason to explain where whta the typeclass is for
| /-- Notation typeclass for substitution, t[n := s] ≃ t.sub n s | |
| which substitute nth variable in t with s. -/ | |
| instance : Cslib.HasSubstitution Term Nat Term | |
| where subst := sub | |
| instance : Cslib.HasSubstitution Term Nat Term where | |
| subst := sub |
Also, was this written by an AI?
There was a problem hiding this comment.
Sorry, I do not know about the style. This part is written by me.
Main contributions
Par) and its basic properties.Diamond,Confluent) for binary relations.The development follows the classical proof strategy:
parallel reduction -> diamond -> confluence -> Church–Rosser.Design choices
(
Diamond,Confluent) to keep the proof modular.Use of AI