Zulip Chat Archive
Stream: general
Topic: simp simp
Eric Wieser (Dec 06 2021 at 16:04):
In this example I need to call simp
twice to close the goal:
import data.dfinsupp
import algebra.module.submodule
@[congr[
lemma set_like.dep_congr {ι α β P} [set_like P α]
{p : ι → P} (f : Π i, p i → β) :
∀ {i j} (x : p i) (h : i = j), f i x = f j ⟨x, h ▸ x.prop⟩
| i _ ⟨x, px⟩ rfl := rfl
variables {ι R M : Type*}
[decidable_eq ι] [add_monoid ι]
[semiring R] [add_comm_monoid M] [module R M]
example (p : ι → submodule R M) :
@dfinsupp.single _ (λ i, p i) _ _ (multiplicative.to_add 1) ⟨0, submodule.zero_mem _⟩ =
dfinsupp.single 0 ⟨0, submodule.zero_mem _⟩ :=
begin
dsimp only, -- delta reduce an instance argument, so that simp has to make real progress
simp,
simp,
end
Is my @[congr]
lemma bad?
Gabriel Ebner (Dec 06 2021 at 16:05):
Are you sure that congr lemma is even used? (The head symbol is a variable, so it won't be found in the index.)
Eric Wieser (Dec 06 2021 at 16:06):
Yes, the second simp
fails without it
Eric Wieser (Dec 06 2021 at 16:08):
(and the first one amounts to a edited so that the first dsimp only
that cleans up an instance argument)simp
fails without @[congr]
Eric Wieser (Dec 06 2021 at 16:18):
I suspect the problem is that the congr lemma doesn't let x
be replaced with some y
on the RHS, but also I can't work out how to state that in a way that congr
accepts
Eric Wieser (Dec 06 2021 at 16:29):
set_like
isn't to blame either, this fails with a submodule-specific lemma too:
@[congr]
lemma submodule.dep_congr {ι β}
{p : ι → submodule R M} (f : Π i, p i → β) :
∀ {i j} (x : p i) (h : i = j), f i x = f j ⟨x, h ▸ x.prop⟩
| i _ ⟨x, px⟩ rfl := rfl
Gabriel Ebner (Dec 06 2021 at 16:32):
The problem here is the f
, not the assumptions.
Eric Wieser (Dec 06 2021 at 16:36):
If I replace f
with something specific like pi.single
, then @[congr]
rejects the lemma:
@[congr]
lemma set_like.dep_congr {ι α P} [decidable_eq ι] [set_like P α]
{p : ι → P} [Π (i : ι), has_zero ↥(p i)] :
∀ {i j} (x : p i) (h : i = j), pi.single i x = pi.single j ⟨x, h ▸ x.prop⟩
| i _ ⟨x, px⟩ rfl := rfl
Gabriel Ebner (Dec 06 2021 at 16:37):
Right, because it won't work in every instance (only when the codomain (p in your example) is non-dependent).
Eric Wieser (Dec 06 2021 at 16:39):
But the codomain of pi.single
is dependent in this case?
Gabriel Ebner (Dec 06 2021 at 16:40):
Ah, now I see.
Eric Wieser (Dec 06 2021 at 16:43):
Is the problem that this only applies to specific invocations of pi.single
?
Gabriel Ebner (Dec 06 2021 at 16:47):
Yes, that's what the check ensures. I think that check could be removed in core without breaking anything. The simplifier does the matching using unification anyhow afaict.
Eric Wieser (Dec 06 2021 at 16:49):
Conversely, should @[congr]
be rejecting my original lemma?
Gabriel Ebner (Dec 06 2021 at 16:49):
If core supported this kind of congr lemma, then you should also allow rewriting in x
, i.e., something like i = j → x.1 = y → pi.single i x = pi.single j ⟨y, ...⟩
.
Gabriel Ebner (Dec 06 2021 at 16:50):
The set_like.dep_congr
lemma is bad because 1) it does higher-order matching, and 2) doesn't allow rewriting in x, and 3) potentially applies to every subterm. There is a lot of stuff the simplifier doesn't like but doesn't reject either, which is fine, we've got linters for that.
Eric Wieser (Dec 06 2021 at 16:53):
x.1 = y
isn't allowed in the congr lemma, annoyingly:
-- invalid congruence lemma, 'set_like.dep_congr' argument #13 is not a valid hypothesis, the
-- left-hand-side contains unresolved parameters
@[congr]
lemma set_like.dep_congr {ι α β P} [set_like P α]
{p : ι → P} (f : Π i, p i → β) :
∀ {i j} (x : p i) (y : α) (h : i = j) (h1 : x.1 = y), f i x = f j ⟨y, h1 ▸ h ▸ x.prop⟩
| i _ ⟨x, px⟩ y rfl rfl := rfl
Eric Wieser (Dec 06 2021 at 16:53):
Nor any other attempt to state something like that I can think of, like x = ⟨y.1, h.symm ▸ y.prop⟩
-- invalid congruence lemma, 'set_like.dep_congr' argument #13 is not a valid hypothesis, the
-- right-hand-side must be of the form (m l_1 ... l_n) where m is parameter that was not
-- 'assigned/resolved' yet and l_i's are locals
Gabriel Ebner (Dec 06 2021 at 16:59):
This would be accepted (but it still has the f issue):
@[congr]
lemma set_like.dep_congr {ι α β P} [set_like P α]
{p : ι → P} (f : Π i, p i → β) :
∀ {i j} (x : p i) (y) (h : i = j) (h1 : x = y), f i x = f j ⟨y, by cases x; subst h1; subst h; assumption⟩
| i _ ⟨x, px⟩ y rfl rfl := rfl
Eric Wieser (Dec 06 2021 at 17:01):
That has y : p i
rather than y : p j
Eric Wieser (Dec 06 2021 at 17:01):
I should have mentioned that I tried that one; but with that one even simp, simp, simp, simp
doesn't close the goal about pi.single
...
Gabriel Ebner (Dec 06 2021 at 17:08):
At least simp; refl
works.
Gabriel Ebner (Dec 06 2021 at 17:08):
@[congr]
lemma set_like.dep_congr {ι α β P} [set_like P α]
{p : ι → P} (f : Π i, p i → β) :
∀ {i j} (x : p i) (y) (h : i = j) (h1 : x = y), f i x = f j ⟨y.1, by cases x; subst h1; subst h; assumption⟩
| i _ ⟨x, px⟩ y rfl rfl := rfl
Eric Wieser (Dec 06 2021 at 17:09):
It works for my original congr
lemma too though
Eric Wieser (Dec 06 2021 at 17:10):
(also that last snippet differs only in coe vs .1; did you find that makes a difference?)
Eric Wieser (Dec 06 2021 at 17:11):
Oh wow it does, thanks!
Eric Wieser (Dec 06 2021 at 17:14):
Although I still need multiple simp
s in some cases:
example (p : ι → submodule R M) (x : M) (h : x = 0) :
@pi.single ι (λ i, p i) _ _ (multiplicative.to_add 1) ⟨0, submodule.zero_mem _⟩ =
pi.single 0 ⟨x, by simp [h, submodule.zero_mem _]⟩ :=
begin
dsimp only,
simp, -- leaves behind a `⟨0, _⟩.val` which isn't simp-normal!
simp, -- gets rid of the above
subst h,
end
Gabriel Ebner (Dec 06 2021 at 17:28):
If congr lemmas allowed complex arguments you could have a second congr lemma of the form pi.single i ⟨x, h⟩ = pi.single j ⟨y, h⟩
which would avoid the iota-reduction.
Eric Wieser (Dec 06 2021 at 17:29):
Yeah, really that's what I'd like to be able to do
Eric Wieser (Dec 06 2021 at 17:29):
Just to check, do you think it's reasonable to expect simp
to be able to close this type of goal?
Gabriel Ebner (Dec 06 2021 at 17:30):
Yes.
Gabriel Ebner (Dec 06 2021 at 17:31):
It should be able to rewrite here.
Eric Wieser (Dec 06 2021 at 17:34):
For this particular goal it seems I can get by with my original congr lemma, and the pi.single_inj
lemma in #10644
Eric Wieser (Dec 06 2021 at 17:34):
But that only works when the dependent function is injective
Eric Wieser (Dec 06 2021 at 17:34):
Can Lean 4 handle this type of thing?
Gabriel Ebner (Dec 06 2021 at 17:39):
The original congr lemma is bad and shouldn't be used, it does higher-order matching on every subterm.
Eric Wieser (Dec 06 2021 at 17:42):
Which is a bad thing because of performance I assume
Gabriel Ebner (Dec 06 2021 at 17:43):
Also because of unpredictability.
Last updated: Dec 20 2023 at 11:08 UTC