feat: LambdaCalculus.LocallyNameless.Coc#392
feat: LambdaCalculus.LocallyNameless.Coc#392matthunz wants to merge 19 commits intoleanprover:mainfrom
LambdaCalculus.LocallyNameless.Coc#392Conversation
|
Hi, thanks for your interest in contributing! Can I ask why the jump to CoC for this named representation of binding? It is a little uncommon to do this style at all, so there's not much else to build off yet. I was hoping that STLC and System F would get filled out first to work out any kinks before more complex type systems. We are planning to add well scoped indices as an alternative in the next few months or so, but if your interest is formalizing CoC right now would you be interested in doing so in the locally nameless style? This would be much easier to review in comparison to what we already have and prior work in Rocq. |
LambdaCalculus.Named.CocLambdaCalculus.LocallyNameless.Coc
|
Hey 👋 thanks so much for the feedback! I wanted to go the named representation route at first because it felt more natural to me coming from functional programming but I'm definitely unsure of how to prove things like well-formedness with that approach. I'd be thrilled if we can fit this in here somehow given the current plans, here's what I did for now:
I think the biggest remaining features would now be reduction and the related proofs to tie everything together, which might be a somewhat significant undertaking 😅 happy to defer to your judgement on what the scope of this PR should be |
chenson2018
left a comment
There was a problem hiding this comment.
Some of this looks good, in particular thank you for mostly following conventions from the System F formalization. There are a few important places however where I'm not sure about the definitions. Because these are tricky to get right I suggest closely following prior work like the formalization from Charguéraud I link below.
| /-- Pi type. -/ | ||
| | pi : Term Var → Term Var → Term Var | ||
| /-- Type universe. -/ | ||
| | type : Term Var |
There was a problem hiding this comment.
We probably want this to be ℕ → Term Var as well.
There was a problem hiding this comment.
Makes sense 👍 I was just going with the simple universal type at first
Changed in 12c85b0
| abbrev Env (Var : Type u) := Finset (Var × Term Var) | ||
|
|
||
| def Env.dom [DecidableEq Var] : Env Var → Finset Var := Finset.image Prod.fst |
There was a problem hiding this comment.
I would expect we reuse LocallyNameless.Context instead of this abbrev.
|
|
||
| /-- Variable opening of the ith bound variable. -/ | ||
| @[scoped grind =] | ||
| def openingRec (i : ℕ) (s : Term Var) : Term Var → Term Var |
There was a problem hiding this comment.
We should name this consistently as openRec and open' with the other typesystems.
| | abs (L : Finset Var) : σ.LC → (∀ x ∉ L, LC (t₁ ^ᵗ fvar x)) → LC (abs σ t₁) | ||
| | pi (L : Finset Var) : σ.LC → (∀ x ∉ L, LC (t₁ ^ᵗ fvar x)) → LC (pi σ t₁) |
There was a problem hiding this comment.
For CoC, the variable σ is a term, as opposed to System F where it was a type. I'd update the variable names accordingly to use t₁ and t₂.
There was a problem hiding this comment.
Makes sense I think my copy-paste is showing there lol, changed in 58caddf
|
|
||
| /-- A locally closed term is unchanged by opening. -/ | ||
| lemma openingRec_lc [HasFresh Var] {σ τ : Term Var} (lc : σ.LC) : σ = σ⟦X ↝ τ⟧ := by | ||
| classical |
There was a problem hiding this comment.
This is for decidable equality? I'd rather make this explicit as a typeclass parameter.
There was a problem hiding this comment.
Yeah exactly I was just following what the linter said there, adjusted to match the conventions in 827087b
There was a problem hiding this comment.
Ah I see, you mean the linter.unusedDecidableInType linter? This will trigger because it is unaware of the typeclass requirements that happen within the proof for free_union. I have unset this in several places for lambda calculi.
| open Term | ||
|
|
||
| /-- β-equivalence. -/ | ||
| inductive BetaEquiv : Term Var → Term Var → Prop |
There was a problem hiding this comment.
This definition looks very different from what I expected. See for instance the definition in the Rocq formalization I closely followed for other type systems.
There was a problem hiding this comment.
Ah I see BetaEquiv was a little lacking 😅 this should now match Chargueraud's representation d6afe92
| BetaEquiv := BetaEquiv | ||
|
|
||
| /-- Typing judgement -/ | ||
| inductive Typing [DecidableEq Var] : Env Var → Term Var → Term Var → Prop |
There was a problem hiding this comment.
I was expecting to see a mutual block also defining well-formed contexts.
There was a problem hiding this comment.
Appreciate the hint! Your idea about having these be mutually-recursive and Chargueraud's repo finally got me to see how to do this e69ac78
| /-- An environment is well-formed if it binds each variable exactly once to a well-formed type. -/ | ||
| inductive Env.Wf : Env Var → Prop | ||
| | nil : Wf {} | ||
| | cons : Wf Γ → Term.Wf Γ τ → x ∉ Γ.dom → Wf ({⟨x, τ⟩} ∪ Γ) |
There was a problem hiding this comment.
I don't think this is right. Because of the dependent types aspect, we need a typing derivation before adding to the context, right?
There was a problem hiding this comment.
Ah yeah the context of dependent types was the part I struggled with quite a bit. I had a version of Coquand's algorithm for type checking using this simple context but for this actual formalization I guess that feels pretty weak.
Changed to Chargueraud's representation in e69ac78
…fit current conventions
| open Term | ||
|
|
||
| /-- β-reduction. -/ | ||
| inductive BetaEquiv : Term Var → Term Var → Prop |
There was a problem hiding this comment.
I should have mentioned previously. This should use the reduction_sys attribute to get notation, because this is still reduction and not the equivalence (reflexive symmetric transitive closure), right? I would remove the HasBetaEquiv class and use this.
There was a problem hiding this comment.
Oh that's super interesting 🤔 I'm not sure I fully understand how this works but it looks like if I have @[reduction_sys "β"] attribute on BetaEquiv, then using A ↠β B in the conversion Typing judgement would work like multi-step reduction? It seems to be working in 4f202b4
There was a problem hiding this comment.
Yes, this looks correct. It is a custom attribute that we use in CSLib, with some docs at here.
…i-step beta reduction
|
At first glance your changes about the feedback I gave look good. I will give it a closer review hopefully later this week. It seems there is some new material about reduction now? You had asked about scope, and while there's no hard limit I think at ~450 LoC this is a nice upper bound for what is preferable to review at once. |
|
Thank you for the mentoring here! Now that β-reduction is in this port would just need β*-reduction, the Church-Rosser theorem, and conversion to be fully complete (as long as what's here is correct so far...). I'll hold off for now, please let me know if you have any more notes 😄 |
No problem, happy to help!
By β*-reduction, you mean the reflexive transitive closure, right? When you did And in general yes, we'll want all these other things you mention, but in small chunks! 😁
I think there will be one or two definitions we might what to generalize, but I can help out with this when I do my second round of reviewing. |
Summary
Adds basic syntax and typing judgments for the Calculus of Constructions following Coquand's algorithm. I tried to keep everything as close to other lambda calculi in this project as well as general code style. Some of the lemmas from that paper are noticeably missing but I'm hoping this can be an OK first cut 😃
LambdaCalculus.LocallyNameless.CocCslib.Foundations.Syntax.HasBetaEquivHasBetaEquiv(similar toHasAlphaEquiv) for the notationA =β B