-
Notifications
You must be signed in to change notification settings - Fork 0
New issue
Have a question about this project? Sign up for a free GitHub account to open an issue and contact its maintainers and the community.
By clicking “Sign up for GitHub”, you agree to our terms of service and privacy statement. We’ll occasionally send you account related emails.
Already on GitHub? Sign in to your account
feat: add simple co-inductive predicates #17
base: master
Are you sure you want to change the base?
Conversation
src/Lean/Elab/Coinductive.lean
Outdated
/- #check Lean.Elab.Binders.to -/ | ||
|
There was a problem hiding this comment.
Choose a reason for hiding this comment
The reason will be displayed to describe this comment to others. Learn more.
/- #check Lean.Elab.Binders.to -/ |
src/Lean/Elab/Coinductive.lean
Outdated
we can safely coerce syntax of these categories -/ | ||
instance : Coe (TSyntax ``bb) (TSyntax ``bracketedBinder) where coe x := ⟨x.raw⟩ |
There was a problem hiding this comment.
Choose a reason for hiding this comment
The reason will be displayed to describe this comment to others. Learn more.
we can safely coerce syntax of these categories -/ | |
instance : Coe (TSyntax ``bb) (TSyntax ``bracketedBinder) where coe x := ⟨x.raw⟩ | |
we can safely coerce syntax of these categories. -/ | |
instance : Coe (TSyntax ``bb) (TSyntax ``bracketedBinder) where coe x := ⟨x.raw⟩ |
Let's not worry about mutuals at all in this first PR |
There was a problem hiding this comment.
Choose a reason for hiding this comment
The reason will be displayed to describe this comment to others. Learn more.
I gave it a look over. @Equilibris it would help a lot if you did a pass and document all the various functions that you've defined
This doesn't feel ready to be PRd to core yet. I think we should look into how hard it would be to go the proper route and elaborate into Expr
s
src/Lean/Elab/Coinductive.lean
Outdated
/- derivingClasses : Array Lean.Elab.DerivingClassView -/ | ||
/- computedFields : Array Lean.Elab.Command.ComputedFieldView -/ |
There was a problem hiding this comment.
Choose a reason for hiding this comment
The reason will be displayed to describe this comment to others. Learn more.
/- derivingClasses : Array Lean.Elab.DerivingClassView -/ | |
/- computedFields : Array Lean.Elab.Command.ComputedFieldView -/ |
Just remove these if we don't want to support them
src/Lean/Elab/Coinductive.lean
Outdated
structure CoInductiveView.CtorView where | ||
ref : Syntax | ||
modifiers : Modifiers | ||
declName : Name | ||
binders : TSyntaxArray ``Lean.Parser.Term.bracketedBinder | ||
type? : Option Term | ||
deriving Inhabited |
There was a problem hiding this comment.
Choose a reason for hiding this comment
The reason will be displayed to describe this comment to others. Learn more.
Isn't this the exact same as the already existing CtorView
, do you reckon we could just reuse that struct instead of defining our own?
There was a problem hiding this comment.
Choose a reason for hiding this comment
The reason will be displayed to describe this comment to others. Learn more.
The reason I defined this is because the original uses Syntax
instead of TSyntax
at multiple places. I can change over to theirs and add casts and stuff if you'd prefer
if ctorModifiers.isPrivate && modifiers.isPrivate then | ||
throwError "invalid 'private' constructor in a 'private' inductive datatype" | ||
if ctorModifiers.isProtected && modifiers.isPrivate then | ||
throwError "invalid 'protected' constructor in a 'private' inductive datatype" |
There was a problem hiding this comment.
Choose a reason for hiding this comment
The reason will be displayed to describe this comment to others. Learn more.
if ctorModifiers.isPrivate && modifiers.isPrivate then | |
throwError "invalid 'private' constructor in a 'private' inductive datatype" | |
if ctorModifiers.isProtected && modifiers.isPrivate then | |
throwError "invalid 'protected' constructor in a 'private' inductive datatype" | |
if ctorModifiers.isPrivate && modifiers.isPrivate then | |
throwError "invalid 'private' constructor in a 'private' coinductive predicate" | |
if ctorModifiers.isProtected && modifiers.isPrivate then | |
throwError "invalid 'protected' constructor in a 'private' coinductive predicate" |
I assume you copied this code from somewhere, can we not reuse that?
There was a problem hiding this comment.
Choose a reason for hiding this comment
The reason will be displayed to describe this comment to others. Learn more.
Yes this is almost identical to the code to generate an InductiveView
but the difference is TSyntax
as mentioned above. Once again if its preferred to use Syntax
we can just use theirs.
src/Lean/Elab/Coinductive.lean
Outdated
|
||
namespace CoInductiveView | ||
|
||
def CtorView.ofStx (declName : Name) (modifiers : Modifiers) (ref : Syntax) : CommandElabM CoInductiveView.CtorView := do |
There was a problem hiding this comment.
Choose a reason for hiding this comment
The reason will be displayed to describe this comment to others. Learn more.
docstring?
src/Lean/Elab/Coinductive.lean
Outdated
|
||
return { ref, modifiers := ctorModifiers, declName := ctorName, binders := binders.getArgs.map (⟨·⟩), type? := type?.map (⟨·⟩) } | ||
|
||
def ofModifiersAndStx (modifiers : Modifiers) (decl : Syntax) : CommandElabM CoInductiveView := do |
There was a problem hiding this comment.
Choose a reason for hiding this comment
The reason will be displayed to describe this comment to others. Learn more.
docstring?
info: inductive Bisim.Shape : (fsm : FSM) → ((fsm : FSM) → fsm.S → fsm.S → Prop) → fsm.S → fsm.S → Prop | ||
number of parameters: 4 | ||
constructors: | ||
Bisim.Shape.step : ∀ {fsm : FSM} {Bisim : (fsm : FSM) → fsm.S → fsm.S → Prop} {s t : fsm.S}, | ||
(fsm.A s ↔ fsm.A t) → (∀ (c : Nat), Bisim fsm (fsm.d s c) (fsm.d t c)) → Bisim.Shape fsm Bisim s t | ||
-/ |
There was a problem hiding this comment.
Choose a reason for hiding this comment
The reason will be displayed to describe this comment to others. Learn more.
This doesn't feel right. FSM
is a fixed parameter to Bisim
(it is given as a binder, before the :
), and should not show up in the motive. That is, I would've expected this to have type
(fsm : FSM) → (fsm.S → fsm.S → Prop) → fsm.S → fsm.S → Prop
src/Lean/Elab/Coinductive.lean
Outdated
-- In theory we could make this handle types by simply changing the existential quantification but this would yield some pretty funny results | ||
let .node _ ``Parser.Term.prop _ := out.raw | throwErrorAt out "Expected return type to be a Prop" | ||
return Prod.mk view argArr |
There was a problem hiding this comment.
Choose a reason for hiding this comment
The reason will be displayed to describe this comment to others. Learn more.
How would you change the existential? The reason this works is because Prop
is impredicative (which is a funny way of saying that Prop -> Prop
is of type Prop
). Once you start looking at types, you run into the issue that Type -> Type
lives in Type 1
, causing nasty universe bumps.
If you meant "pull in QpfTypes", sure, but that is very explicitly not something that core wants
-- In theory we could make this handle types by simply changing the existential quantification but this would yield some pretty funny results | |
let .node _ ``Parser.Term.prop _ := out.raw | throwErrorAt out "Expected return type to be a Prop" | |
return Prod.mk view argArr | |
let .node _ ``Parser.Term.prop _ := out.raw | throwErrorAt out "Expected return type to be a Prop" | |
return Prod.mk view argArr |
src/Lean/Elab/Coinductive.lean
Outdated
builtin_initialize | ||
registerTraceClass `Elab.CoInductive | ||
|
||
structure CoInductiveView.CtorView where |
There was a problem hiding this comment.
Choose a reason for hiding this comment
The reason will be displayed to describe this comment to others. Learn more.
structure CoInductiveView.CtorView where | |
structure CoinductiveView.CtorView where |
Very minor nit, but I'd consider coinductive to be one word, and thus not capitalize the I
in names
src/Lean/Elab/Coinductive.lean
Outdated
def extractName : Syntax → Name | ||
| .ident _ _ nm _ => nm | ||
| _ => .anonymous |
There was a problem hiding this comment.
Choose a reason for hiding this comment
The reason will be displayed to describe this comment to others. Learn more.
this exists already, Ident.getId
or something similar
src/Lean/Elab/Coinductive.lean
Outdated
partial def typeToArgArr (type : Term) : Array Term × Term := Prod.map List.toArray id $ go type.raw | ||
where go | ||
| .node _ ``Parser.Term.arrow #[hd, _, tail] => Prod.map (⟨hd⟩ :: ·) id $ go tail | ||
| rest => ⟨[], ⟨rest⟩⟩ | ||
|
||
def appsToArgArr (type : Term) : Array Term × Term := match type.raw with | ||
| .node _ ``Parser.Term.app #[v, cont] => ⟨cont.getArgs.map (⟨·⟩), ⟨v⟩⟩ | ||
| rest => ⟨#[], ⟨rest⟩⟩ | ||
|
There was a problem hiding this comment.
Choose a reason for hiding this comment
The reason will be displayed to describe this comment to others. Learn more.
Manipulating Syntax like this feels rather brittle. This was fine for QpfTypes, where I number one priority was to get something that at least kind of works, but if we want to PR to core, we should strongly consider going the proper route and elaborating into Expr
s
@@ -0,0 +1,253 @@ | |||
/- | |||
Copyright (c) 2020 Microsoft Corporation. All rights reserved. |
There was a problem hiding this comment.
Choose a reason for hiding this comment
The reason will be displayed to describe this comment to others. Learn more.
Should this have a Lean-FRO copyright?
Add basic implementation of co-inductive predicates using cofix points expressed as existential quantifications. This is done by first generating a
Shape
inductive datatype then quantifying over this. For example, if this were to be hand implemented in the context of a bisimulation it looks something like this:(example by @alexkeizer )
This is writable if hard, rather, a new syntax is added in this PR that looks like the following:
An example of what this yields is generated in the test
coindBisim.lean
.Currently, this does only hold for co-inductive predicates (i.e. the ones that reside in
Prop
).The generation of shape types is done by taking the original written syntax and simply adding another parameter with the name and signature of the entire expression. In the case of
Bisim
this shape looks like this:The fixed point is then found with the same means as listed above.
TODOs:
toBinderViews
alternatives