Skip to content
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

RFC: mutual structures #4182

Closed
ice1000 opened this issue May 15, 2024 · 6 comments · Fixed by #6125
Closed

RFC: mutual structures #4182

ice1000 opened this issue May 15, 2024 · 6 comments · Fixed by #6125
Labels
P-low We are not planning to work on this issue RFC Request for comments

Comments

@ice1000
Copy link

ice1000 commented May 15, 2024

Proposal

I think structures should work in mutual blocks. #2587 reports an error message related to this feature, and everyone commented in the issue expected this to work (I expect this to fulfill the "community feedback" requirement), but the issue is closed as it's not about making it work.

A simple example use case can also be found in #2587.

Impact

Add 👍 to issues you consider important. If others benefit from the changes in this proposal being added, please ask them to add 👍 to it.

@ice1000 ice1000 added the RFC Request for comments label May 15, 2024
@arthur-adjedj
Copy link
Contributor

arthur-adjedj commented May 16, 2024

Lean (kernel included) considers an inductive type to be "structure-like" iff it is non-recursive, not indexed, and has a single constructor. Because structure types benefit from special treatments such as having primitive projections and eta-conversion, it would be unwise to blindly adopt that RFC. In particular, eta-conversion on recursive/mutual structures can lead to a form of undecidability of defeq that's quite hard to deal with.

One possibility to handle this feature would be to allow the structure syntax to construct inductive types which are not structure-like. This would require no change to the kernel. However, such "structure but not structure-like" types would lose both eta-conversion and primitive projections, and would only really benefit from having the notations that are exclusive to structures such as {foo := ...}. I am not certain of the added benefits of this feature, but I am all for having better error messages when using structures in mutual blocks.

@nomeata
Copy link
Collaborator

nomeata commented May 16, 2024

I felt silly once having had to write the projection functions for a almost-structure (it was recursive) by hand because I couldn't see structure syntax, so I think there is some added benefit.

@arthur-adjedj
Copy link
Contributor

Perhaps Lean could benefit from dissociating between structures and non-recursive structures then, including in the kernel. In particular, a recursive structure , could still benefit from having primitive projections, which are great for performance, without having eta-conversion.

@ice1000
Copy link
Author

ice1000 commented May 16, 2024

@arthur-adjedj can you enlighten me on how does structure eta conversion gets undecidable?

@arthur-adjedj
Copy link
Contributor

Also, I believe some lean libraries already offer a way to automatically generate "projections" on non-structures, notably this one

@arthur-adjedj
Copy link
Contributor

arthur-adjedj commented May 16, 2024

@arthur-adjedj can you enlighten me on how does structure eta conversion gets undecidable?

Consider the following (recursive) structure:

structure Foo where
  foo : Foo

When comparing two arbitrary neutral terms, i.e variables x =?= y : Foo. The type-checker might want to eta-expand those values recursively, checking against x.1 =?= y.1 : Foo, then x.1.1 =?= y.1.1, so on and so forth. Two things to note:

  • Such eta-expansion on i.e variables can be desirable. A (proof-relevant) structure might only contain proof-irrelevant fields for example
  • I don't think such an infinite loop would trigger in Lean in practice currently. Because conversion is untyped in the system, Lean has no way to trigger eta-conversion on two neutrals, and only triggers it when one of the two sides is already built from the constructor. All I am arguing is that eta on recursive records is tricky/non-trivial to handle, and might not be necessarily worth the risk.

I believe Agda supports recursive records, as well as eta-expansion, and also uses typed conversion, which allows it to eta-expand neutrals. Does anyone know how it handles this issue ?

@leanprover-bot leanprover-bot added the P-low We are not planning to work on this issue label Aug 23, 2024
github-merge-queue bot pushed a commit that referenced this issue Nov 22, 2024
This PR adds support for `structure` in `mutual` blocks, allowing
inductive types defined by `inductive` and `structure` to be mutually
recursive. The limitations are (1) that the parents in the `extends`
clause must be defined before the `mutual` block and (2) mutually
recursive classes are not allowed (a limitation shared by `class
inductive`). There are also improvements to universe level inference for
inductive types and structures. Breaking change: structure parents now
elaborate with the structure in scope (fix: use qualified names or
rename the structure to avoid shadowing), and structure parents no
longer elaborate with autoimplicits enabled.

Internally, this is a large refactor of both the `inductive` and
`structure` commands. Common material is now in
`Lean.Elab.MutualInductive`, and each command plugs into this mutual
inductive elaboration framework with the logic specific to the
respective command. For example, `structure` has code to add projections
after the inductive types are added to the environment.

Closes #4182
Sign up for free to join this conversation on GitHub. Already have an account? Sign in to comment
Labels
P-low We are not planning to work on this issue RFC Request for comments
Projects
None yet
Development

Successfully merging a pull request may close this issue.

4 participants