-
Notifications
You must be signed in to change notification settings - Fork 421
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: f.eq_unfold lemmas #5110
Comments
nomeata
added a commit
that referenced
this issue
Aug 23, 2024
With this, lean produces the following zoo of rewrite rules: ``` Option.map.eq_1 : Option.map f none = none Option.map.eq_2 : Option.map f (some x) = some (f x) Option.map.eq_def : Option.map f p = match o with | none => none | (some x) => some (f x) Option.map.unfold : Option.map = fun f p => match o with | none => none | (some x) => some (f x) ``` The `f.unfold` variant is especially useful to rewrite with `rw` under binders. This implements and fixes #5110
Edit: Suggesting name |
github-merge-queue bot
pushed a commit
that referenced
this issue
Aug 29, 2024
With this, lean produces the following zoo of rewrite rules: ``` Option.map.eq_1 : Option.map f none = none Option.map.eq_2 : Option.map f (some x) = some (f x) Option.map.eq_def : Option.map f p = match o with | none => none | (some x) => some (f x) Option.map.eq_unfold : Option.map = fun f p => match o with | none => none | (some x) => some (f x) ``` The `f.eq_unfold` variant is especially useful to rewrite with `rw` under binders. This implements and fixes #5110
Sign up for free
to join this conversation on GitHub.
Already have an account?
Sign in to comment
Proposal
For a function definition like
Option.map
we currently (well, for non-recursive only after #4154) create two kinds of rewrite lemmas 👍🏻map.eq_<n>
: Matches whenmap
is fully applied and there are constructors (map f none = …
)map.eq_def
: Matches whenmap
is fully applied (map f x = match x with …
)Users can use this with
simp
orrw
to control how aggressive the function should be unfolded. For example,rw [Option.map]
will leavemap x
in place, butrw [Option.map.eq_def]
will unfold it.In this “algebra of rewrite specificity” there is a spot that we are missing and that might be useful:
map.eq_unfold
: Matches everymap
, even under applied or under binders (map = fun f x => match x with …
).One particular use-case for this is to rewrite with
rw
under binders where that isn't possible withf.eq_def
:This would probably also have helped with #5026.
Naming
As always, naming is hard. Some options:
f.unfold
-- clashes with too many existing theoremsf.const_eq
f.eq_spec
-- goes well with.eq_def
and.eq_n
f.def
-- probably not, we had this name for what’s nowf.eq_def
and it broke too much.Implementation
Various ways to skin the cat, specially with regard to the existing
getUnfoldFor?
machinery.One plausible path of least disruption is to have a single (non-extensible) generator for
f.eq_unfold
that looks atf.eq_def
to compute the lemma statement (by moving binders to the RHS), and then proves it by rfl if possible and else usingfunext
andf.eq_def
.Future steps
Once this is in, I imagine it might be a worthwhile refactoring to make it so that only the generation of
f.unfold
is extensible (wf, structural, non-rec, maybe #3119), and thenf.eq_def
andf.eq_1
are generated by lean from that definition. More uniform, less code. This should not prevent those theorems to be proven byEq.rfl
if possible.Community Feedback
Ideas should be discussed on the Lean Zulip prior to submitting a proposal. Summarize all prior discussions and link them here.
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.
The text was updated successfully, but these errors were encountered: