Zulip Chat Archive
Stream: mathlib4
Topic: simpNF error behind `simps`
Arien Malec (Feb 01 2023 at 23:33):
In !4#1995 this definition causes a simpNF
error
-- The additive version of `Finsupp.toTinsupp`. Note that this is `noncomputable` because
`Finsupp.hasAdd` is noncomputable. -/
@[simps (config := { fullyApplied := false })]
def finsuppLequivDfinsupp [DecidableEq ι] [Semiring R] [AddCommMonoid M]
[∀ m : M, Decidable (m ≠ 0)] [Module R M] : (ι →₀ M) ≃ₗ[R] Π₀ _i : ι, M :=
{ finsuppEquivDfinsupp with
toFun := Finsupp.toDfinsupp
invFun := Dfinsupp.toFinsupp
map_smul' := Finsupp.toDfinsupp_smul
map_add' := Finsupp.toDfinsupp_add }
the error is
#check @finsuppLequivDfinsupp_apply_apply /- Left-hand side simplifies from
↑(finsuppLequivDfinsupp R).toLinearMap
to
↑(finsuppLequivDfinsupp R)
using
simp only [@LinearEquiv.coe_coe]
but I have no access to the definition that's failing... (I only know this is the definition that fails by using the hack of moving #lint
up the file until it doesn't fail...
Arien Malec (Feb 02 2023 at 01:02):
I tried to nolint
here, but it doesn't help
Arien Malec (Feb 02 2023 at 01:18):
and if I remove the config
section from simps
the lint issue goes away....
Jireh Loreaux (Feb 02 2023 at 02:20):
simps?
will tell you the declarations that simps
is generating.
Arien Malec (Feb 02 2023 at 02:28):
Ah, yes, I see the declaration... What's the fix here?
Arien Malec (Feb 02 2023 at 02:40):
I see in another file that the fix was to add the lemmas manually...
Arien Malec (Feb 02 2023 at 03:09):
And the generated code doesn't typecheck?
Jireh Loreaux (Feb 02 2023 at 04:26):
The fact that the code from the pretty printer doesn't type check isn't too surprising, you may need to massage it a bit.
The problem is that the LHS isn't simplified (i.e., there is some other lemma that simplifies the LHS), which means that sometimes this lemma wouldn't get applied when you want it to (because it will get "skipped over" due to the other simp lemma).
In this case, I personally think it makes sense to replace the LHS of the generated lemma with the one provided by simpNF
(and so you should manually add the simp
lemma).
Arien Malec (Feb 02 2023 at 04:50):
Thanks. Yep, on it as soon as I figure out the types.
Arien Malec (Feb 02 2023 at 05:34):
As an example, simps?
generates (this is one of the ones that simpNF
didn't complain about):
finsuppLequivDfinsupp_apply_apply:
> ∀ {ι : Type u_1} (R : Type u_2) {M : Type u_3} [inst : DecidableEq ι] [inst_1 : Semiring R]
[inst_2 : AddCommMonoid M] [inst_3 : (m : M) → Decidable (m ≠ 0)] [inst_4 : Module R M],
↑(finsuppLequivDfinsupp R).toLinearMap = Finsupp.toDfinsupp
which I've translated as:
@[simp]
theorem finsuppLequivDfinsupp_apply_toAddHom_apply [DecidableEq ι] [Semiring R] [AddCommMonoid M]
[∀ m : M, Decidable (m ≠ 0)] [Module R M]:
↑(finsuppLequivDfinsupp R).toLinearMap.toAddHom = Finsupp.toDfinsupp := sorry
but we get type errors
type mismatch
(finsuppLequivDfinsupp R).toLinearMap.toAddHom
has type
AddHom (?m.64898 →₀ ?m.64899) (Dfinsupp fun _i => ?m.64899) : Type (max ?u.64895 ?u.64897)
but is expected to have type
(?m.64785 →₀ ?m.64786) → Dfinsupp fun _i => ?m.64786 : Type (max ?u.64783 ?u.64784)
(note that it doesn't matter if I take the simps
output more verbatim -- same issues with the below (which is the same thing modulo prettier formatting and previous variable
declarations).
theorem finsuppLequivDfinsupp_apply_toAddHom_apply:
∀ {ι : Type u_1} (R : Type u_2) {M : Type u_3} [inst : DecidableEq ι] [inst_1 : Semiring R]
[inst_2 : AddCommMonoid M] [inst_3 : (m : M) → Decidable (m ≠ 0)] [inst_4 : Module R M],
↑(finsuppLequivDfinsupp R).toLinearMap.toAddHom = Finsupp.toDfinsupp := sorry
Floris van Doorn (Feb 02 2023 at 14:33):
simps
is configured wrong for linearEquiv
, it shouldn't even generate these lemmas, and didn't do this in Lean 3. I will PR a fix, going through all simps
configurations.
There is still one thing I don't understand, maybe @Gabriel Ebner knows what's going on.
If, after the definition of finsuppLequivDfinsupp
in !4#1995, I write the following, then simp
can simplify the LHS of both lemmas, but the linter complains only about 1 of them. Is that expected? Should the linter also complain about lemma2
?
@[simp]
lemma lemma1 [DecidableEq ι] [Semiring R] [AddCommMonoid M]
[∀ m : M, Decidable (m ≠ 0)] [Module R M] :
(↑(finsuppLequivDfinsupp (M := M) R).toLinearMap : (ι →₀ M) → _) =
Finsupp.toDfinsupp := by
simp -- simplifies LHS to `↑(finsuppLequivDfinsupp R)`
rfl
@[simp]
lemma lemma2 [DecidableEq ι] [Semiring R] [AddCommMonoid M]
[∀ m : M, Decidable (m ≠ 0)] [Module R M] (f : ι →₀ M) :
(finsuppLequivDfinsupp (M := M) R).toLinearMap f =
Finsupp.toDfinsupp f := by
simp -- simplifies LHS to `↑(finsuppLequivDfinsupp R) f`
rfl
#lint -- simpNF complains only about lemma1, not about lemma2
Gabriel Ebner (Feb 02 2023 at 17:55):
The only difference between lemma1 and lemma2 is that lemma1's lhs is foo
and lemma2's lhs is foo x
, right? Then it should be clear why only lemma2 is redundant: lemma1 applies to lemma2 but not vice versa.
Floris van Doorn (Feb 02 2023 at 18:43):
Yes, that is exactly the difference.
In this case lemma2 is redundant, because of lemma1, but I am confused why the simpNF
linter doesn't complain about it (lemma2
), even though the LHS is not in simp-normal form.
Gabriel Ebner (Feb 02 2023 at 18:53):
I guess lemma2 is simplified using itself, so it doesn't look like it's redundant.
Floris van Doorn (Feb 02 2023 at 19:07):
In Lean 4 subexpressions are not simplified first? Is this allowed for the same reason that in Lean 3 we could have simp lemmas that specialize earlier simp-lemmas?
Gabriel Ebner (Feb 02 2023 at 20:23):
I think it's more "partial applications are not simplified first", but I'd need to check.
Floris van Doorn (Feb 02 2023 at 20:59):
ok, thanks
Last updated: Dec 20 2023 at 11:08 UTC