[Merged by Bors] - feat: support coercions in the differential geometry elaborators#30307
[Merged by Bors] - feat: support coercions in the differential geometry elaborators#30307grunweg wants to merge 22 commits intoleanprover-community:masterfrom
Conversation
PR summary c7bb7934b2Import changes for modified filesNo significant changes to the import graph Import changes for all files
|
|
I think you're right about coercions being the issue. Perhaps we should just try to coerce everything which isn't a function before
We could do this in
But the easiest and clearest approach is probably just to define something like /-- Ensures that `e` is a function. Attempts to coerce `e` to a function if necessary. -/
def ensureIsFunction (e : Expr) : MetaM Expr := do
let ty ← whnf <|← instantiateMVars <|← inferType e
if ty.isForall then return e else (← coerceToFunction? e).getDM <|
throwError "Expected{indentD e}\nof type{indentD ty}\nto be a function, or to be coercible to \
a function"for convenience (probably in the namespace scoped elab:max "MDiffAt[" s:term "]" ppSpace f:term:arg : term => do
let es ← Term.elabTerm s none
let ef ← ensureIsFun <|← Term.elabTerm f none
let (srcI, tgtI) ← findModels ef es
mkAppM ``MDifferentiableWithinAt #[srcI, tgtI, ef, es](and likewise elsewhere!) :) |
|
Note: we could also use |
1d8f1f1 to
caae86f
Compare
|
Thanks for your detective help! I tried your second approach, and generally it works really well 🎉
|
9190b3b to
9b44efa
Compare
|
This PR/issue depends on:
|
9b44efa to
e1987c5
Compare
Tests still fial, but one is a clear bug in my code
And probably, want to insert a coercion...
e1987c5 to
8353626
Compare
|
I just rebased on top of master, added a last few tests and moved the new meta function to |
Co-authored-by: thorimur <68410468+thorimur@users.noreply.github.com>
thorimur
left a comment
There was a problem hiding this comment.
LGTM after addressing these comments! :)
| mkAppM ``MDifferentiable #[srcI, tgtI, e] | ||
|
|
||
| -- We ensure the type of `n` before checking `f` is a function to provide better error messages | ||
| -- in case e.g. just `n` was forgotten. |
There was a problem hiding this comment.
I like this change! But it should read as follows, right? (If we wanted to support leaving off n, we could change the parser to parse optional arguments in a subsequent PR!)
| -- in case e.g. just `n` was forgotten. | |
| -- in case e.g. `n` and `f` were accidentally swapped. |
There was a problem hiding this comment.
Actually, I mean it as I wrote it: there are some tests for error messages if just n is missing (not swapped). Before this PR, they complain that the first argument (i.e., f) has type E \to M and not WithTop N\infty.
When I checked for the type of f first, this part of the error got lost: see 27ede4a for the details.
I much prefer the error about n first.
Does this make sense?
(I don't think we want to support leaving out n: that information matters, and Lean cannot synthesize it out of thin air.)
There was a problem hiding this comment.
there are some tests for error messages if just n is missing (not swapped).
Hmm, really? I'm surprised—isn't e.g. CMDiffAt f, where n is missing, a parse error?
(That's why I was suggesting the possibility of parsing optional arguments, by the way: not so we could synthesize the data, but so we could at least make it to elaboration, then throw a descriptive error saying that more arguments are needed! :) )
Re: approval for this PR, for any maintainer reading: the precise wording of this comment is all that's being discussed here, which in my opinion is probably not a crucial enough issue to hold up this PR (especially since many opportunities to reword are waiting in the wings). :)
There was a problem hiding this comment.
Hmm, really? I'm surprised—isn't e.g. CMDiffAt f, where n is missing, a parse error?
Actually, you're right: there are commented tests for this, because this is a parse error (as you said).
Let me add parsing optional arguments as a TODO item to #30503.
Co-authored-by: thorimur <68410468+thorimur@users.noreply.github.com>
Strongly agree with both. Would you like to start a zulip discussion? (Medium-term, it would be nice to upstream these to Lean core... that's certainly a better place to put them!) |
|
Thanks for the close look again. I have addressed or responded to all comments. |
| scoped elab:max "MDiffAt[" s:term "]" ppSpace f:term:arg : term => do | ||
| let es ← Term.elabTerm s none | ||
| let ef ← Term.elabTerm f none | ||
| let ef ← ensureIsFunction <|← Term.elabTerm f none |
There was a problem hiding this comment.
| let ef ← ensureIsFunction <|← Term.elabTerm f none | |
| let ef ← ensureIsFunction <| ← Term.elabTerm f none |
(You use <|← consistently, so it seems to be a style choice. But don't we have as a style rule to put spaces around operators?)
There was a problem hiding this comment.
I've added spaces now. It does look a little weird, but consistency seems good.
There was a problem hiding this comment.
Sorry, this may have been my influence; I use <|← consistently. :) @Vierkantor you're right that the style rule is spaces; I'm not sure where I picked this up!
But, I can't tell if <|← is actually more readable (cuts down on tokens and whitespace), or if I've just grown used to it! I like it enough, though, that I at least wanted to discuss it on zulip. :)
| /-- Checks that `e` is a function (i.e. that its type is a `.forallE` after `instantiateMVars` and | ||
| `whnf`). If not, coerces `e` to a function or fails with a descriptive error. -/ | ||
| def Lean.Meta.ensureIsFunction (e : Expr) : MetaM Expr := do | ||
| let ty ← whnf <|← instantiateMVars <|← inferType e | ||
| if ty.isForall then return e else (← coerceToFunction? e).getDM <| | ||
| throwError "Expected{indentD e}\nof type{indentD ty}\nto be a function, or to be coercible to \ | ||
| a function" |
There was a problem hiding this comment.
I would have expected this to exist already! But searching through lean4/batteries/mathlib4 for usages of coerceToFunction?, there does not seem to be anything similar.
Do you know if we have something similar for coeSort and coe? If not, can you add them?
There was a problem hiding this comment.
I don't think they exist either; I have just added them. While cargo-culting them was not too hard, a areful review is welcome!
There was a problem hiding this comment.
Side note: would a PR adding these three declarations to core be welcome?
There was a problem hiding this comment.
re upstreaming: No objections from me, but I would probably merge this first and then ask @kmill if core is interested in maintaining them.
There was a problem hiding this comment.
Two weeks later, let me follow-up on this.
@kmill In this PR, I've added a few new functions to Mathlib/Lean/Meta/Basic.lean: Lean.Meta.ensureHasType, Lean.Meta.ensureIsFunction and Lean.Meta.ensureIsSort. Is Lean core interested in maintaining them?
|
✌️ grunweg can now approve this pull request. To approve and merge a pull request, simply reply with |
Co-authored-by: Anne Baanen <Vierkantor@users.noreply.github.com>
Co-authored-by: Anne Baanen <Vierkantor@users.noreply.github.com>
|
Thanks for the review! I'll wait for CI to finish, then hit the merge button. |
|
bors merge |
) Generalise the `CMDiff`, `MDiff` and `mfderiv` elaborators (and its friends) to apply to any object which coerces to a function. We can such speak about the smoothness of a `PartialEquiv`, `OpenPartialHomeomorph` (or the future `ClosedPartialHomeomorph` and `PartialHomeomorph`), smooth section or bundled smooth map without the need for a coercion. As a by-product, add new functions `Lean.Meta.ensure{HasType,IsFunction,IsSort}` which apply the respective coercion if necessary. While at it, add more sections (and section headers) to the test file for the elaborators. Co-authored-by: pre-commit-ci-lite[bot] <117423508+pre-commit-ci-lite[bot]@users.noreply.github.com>
|
Pull request successfully merged into master. Build succeeded: |
…nprover-community#30307) Generalise the `CMDiff`, `MDiff` and `mfderiv` elaborators (and its friends) to apply to any object which coerces to a function. We can such speak about the smoothness of a `PartialEquiv`, `OpenPartialHomeomorph` (or the future `ClosedPartialHomeomorph` and `PartialHomeomorph`), smooth section or bundled smooth map without the need for a coercion. As a by-product, add new functions `Lean.Meta.ensure{HasType,IsFunction,IsSort}` which apply the respective coercion if necessary. While at it, add more sections (and section headers) to the test file for the elaborators. Co-authored-by: pre-commit-ci-lite[bot] <117423508+pre-commit-ci-lite[bot]@users.noreply.github.com>
…nprover-community#30307) Generalise the `CMDiff`, `MDiff` and `mfderiv` elaborators (and its friends) to apply to any object which coerces to a function. We can such speak about the smoothness of a `PartialEquiv`, `OpenPartialHomeomorph` (or the future `ClosedPartialHomeomorph` and `PartialHomeomorph`), smooth section or bundled smooth map without the need for a coercion. As a by-product, add new functions `Lean.Meta.ensure{HasType,IsFunction,IsSort}` which apply the respective coercion if necessary. While at it, add more sections (and section headers) to the test file for the elaborators. Co-authored-by: pre-commit-ci-lite[bot] <117423508+pre-commit-ci-lite[bot]@users.noreply.github.com>
Generalise the
CMDiff,MDiffandmfderivelaborators (and its friends) to apply to any object which coerces to a function. We can such speak about the smoothness of aPartialEquiv,OpenPartialHomeomorph(or the futureClosedPartialHomeomorphandPartialHomeomorph), smooth section or bundled smooth map without the need for a coercion.As a by-product, add new functions
Lean.Meta.ensure{HasType,IsFunction,IsSort}which apply the respective coercion if necessary.While at it, add more sections (and section headers) to the test file for the elaborators.
I have forward-ported this PR to #26221 and not noticed any issues yet.