-
Notifications
You must be signed in to change notification settings - Fork 534
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: termination_by structural #4542
Conversation
More on my preferrence of As a user, these “record terms syntax as part of tactic syntax” feels very clumsy and heavy (not helped by the rather verbose I get this impression for example from the fact the simp syntax offers Maybe if the concrete syntax was a bit less heavy (no |
6e080f6
to
809aca2
Compare
Mathlib CI status (docs):
|
this is in preparation for #4542, and extracts from `findRecArg` the functionality for trying one particular argument. It also refactors the code a bit. In particular * It reports errors in the order of the parameters, not the order of in which they are tried (it tries non-indices first). * For every argument it will say why it wasn't tried, even if the reason is quite obviously (fixed prefix, or `Prop`-typed etc.) Therefore there is some error message churn.
this is in preparation for #4542, and extracts from `findRecArg` the functionality for trying one particular argument. It also refactors the code a bit. In particular * It reports errors in the order of the parameters, not the order of in which they are tried (it tries non-indices first). * For every argument it will say why it wasn't tried, even if the reason is quite obviously (fixed prefix, or `Prop`-typed etc.) Therefore there is some error message churn.
this addresses #4546 the easy way
…mination_by_structurally
…to joachim/termination_by_structurally
This reverts commit 686c2e4.
…mination_by_structurally
This adds support for mutual structural recursive functions. For now this is opt-in: The functions must have a `termination_by structural …` annotation (new since #4542) for this to work: ```lean mutual inductive A | self : A → A | other : B → A | empty inductive B | self : B → B | other : A → B | empty end mutual def A.size : A → Nat | .self a => a.size + 1 | .other b => b.size + 1 | .empty => 0 termination_by structural x => x def B.size : B → Nat | .self b => b.size + 1 | .other a => a.size + 1 | .empty => 0 termination_by structural x => x end ``` The recursive functions don’t have to be in a one-to-one relation to a set of mutually recursive inductive data types. It is possible to ignore some of the types: ```lean def A.self_size : A → Nat | .self a => a.self_size + 1 | .other _ => 0 | .empty => 0 termination_by structural x => x ``` or have more than one function per argument type: ```lean def isEven : Nat → Prop | 0 => True | n+1 => ¬ isOdd n termination_by structural x => x def isOdd : Nat → Prop | 0 => False | n+1 => ¬ isEven n termination_by structural x => x ``` This does not include * Support for nested inductive data types or nested recursion * Inferring mutual structural recursion in the absence of `termination_by`. * Functional induction principles for these. * Mutually recursive functions that live in different universes. This may be possible, maybe after beefing up the `.below` and `.brecOn` functions; we can look into this some other time, maybe when there are concrete use cases. --------- Co-authored-by: Richard Kiss <[email protected]> Co-authored-by: Tobias Grosser <[email protected]>
This implements the
termination_by structural
syntax proposed in #3909.I went with
termination_by structural
over, say,termination_by (config := {method := .structural})
mainly because it waseasier to get going (otherwise I’d have to look into how to define recursive
parsers, as
Parser.config
depends onterm
andtermination_by
is part ofterm. But also because I find it more ergonomic and aesthetic as a user.
But syntax can still change.
The
termination_by?
syntax will no longer force well-founded recursion,and instead the inferred
termination_by structurally
annotation will be shownif structural termination is possible.
While I was it, this fixes #4546 the easy way (log errors about but otherwise
ignore incomplete
termination_by
sets for mutual recursion). Maybe we getmultiple replacements (#4551), but even then this this good behavior.
Involves a bit of shuffling around
TerimationHints
(now validated for aclique already by
PreDefinition.main
) andTerminationArguments
(now liftedout of the
WF
namespace, and a bit simplified).Fixes #3909