Zulip Chat Archive
Stream: lean4
Topic: simp and local lets
Bhavik Mehta (Sep 24 2024 at 10:56):
How is simp meant to interact with local let
s now? I know there were some changes fairly recently but the behaviour doesn't seem to make sense to me right now:
I have two lets c
and d
in my local context, and simp only
is unfolding d
and not c
, which is confusing behaviour to me. In particular this is annoying because I'd like to do the exact opposite (unfold c
and not d
), and I was hoping that simp only [c]
would work, but it's going way too far.
Here's an example with no dependency on mathlib
variable {α : Type}
theorem test {n : Nat} {f : Fin n → α} : False := by
let c (i : Fin n) : Nat := i
let d : Fin n → Nat × Nat := fun i => (c i, c i + 1)
have : ∀ i, (d i).2 ≠ c i * 2 := by
simp only
The simp only unfolds d
but not c
. What I actually wanted - in the original context - was to unfold c
but not d
, which I'd do with simp only [c]
. But since simp only
is unfolding d
too, this breaks my proof idea. How can I use simp
or variants on a goal like this?
Bhavik Mehta (Sep 24 2024 at 11:03):
The same thing happens when turning the config option zeta
off too. zetaDelta says it's off by default, although this example seems to be exactly a zetaDelta reduction, but turning it off explicitly doesn't help either.
Ruben Van de Velde (Sep 24 2024 at 11:06):
I'm surprised as well that d
would be unfolded
Bhavik Mehta (Sep 24 2024 at 11:08):
To make it even more surprising, changing d
to fun i => c i
returns the behaviour back to normal!
Damiano Testa (Sep 24 2024 at 11:09):
Mathlib has unfold_let c
: does that do what you want? It still does not answer why simp
starts unfolding the latest let
, but maybe it is good as a workaround.
Bhavik Mehta (Sep 24 2024 at 11:10):
Ah yeah this is a nice workaround in my context, thanks. (The workaround I was using was to edit: unfortunately not, because I want to generalize
to force simp only
not to unfold too far, but yours is cleaner!)simp only
with some other lemmas afterwards, and that one goes too far instead
Floris van Doorn (Sep 24 2024 at 12:26):
Turning the proj
option off does what you want in this case:
theorem test {α : Type} {n : Nat} {f : Fin n → α} : False := by
let c (i : Fin n) : Nat := i
let d : Nat × Nat := (1, 2)
have : ∀ i, d.2 ≠ c i * 2 := by
simp (config := {proj := false}) only [c]
I think it's a good idea to have the "projection-reduction" be aware of the zetaDelta
(and zeta
) options, and be more conservative if they are off.
Floris van Doorn (Sep 24 2024 at 12:26):
maybe open an RFC?
Floris van Doorn (Sep 24 2024 at 14:42):
lean4#5455 (to keep things linked)
Bhavik Mehta (Sep 24 2024 at 14:43):
Oops sorry, meant to do this myself. Thanks!
Tomas Skrivan (Sep 24 2024 at 19:19):
Last time I investigated a similar issue the offending call to whnf
is in project?
which is called in reduceProj?
which is called in reduceProjFn?
which is part of the simplifier. I think that whnf
call should inherit config from the simplifier. However I'm not sure what to do about whnf
cache.
Tomas Skrivan (Sep 24 2024 at 19:21):
The similar issue is that
(let a:=x+x; let b:= x*x; (a,b)).1
reduces to
x+x
instead of to
let a:= x+x; a
with zeta:=false
I will reinvestigate this and comment on the GitHub issue.
Last updated: May 02 2025 at 03:31 UTC