Zulip Chat Archive
Stream: new members
Topic: Replace a term with its definition
Pieter Cuijpers (Nov 11 2022 at 12:38):
I'm running into the following type of problem regularly, and am wondering if there is a simple way to approach it.
I hope I can explain what I mean clearly.
Consider the Lean4 code at the end of this post.
In it, I define a number of classes, an instance, and a property, and subsequently want to check that the instance has the property.
What I run into is illustrated by the first "state" - which I commented in.
The goal simply states: is_associative.
Now it seems that I have to look-up is_associative manually and then conclude I can get on with my prove using intro x y z.
A 'better' way would be if I had a way to let Lean unfold the definition of is_associative automatically.
Is there a tactic for that?
I run into the same problem again after the intro x y z, because the state then indicates Operator while in principle Lean should be able to unfold that definition into the underlying functions. Actually, I don't even know what to use to finish the proof in this case, so any help there would probably be a good hint in the right direction as well.
class Property (α : Type u) where
contains : α → Prop
class Operation (α : Type u) where
op : α → α → α
class IOperation (α : Type u) where
iop : Property α → α
instance [I : IOperation α] : Operation α where
op := λ x y => I.iop ⟨ λ z => z = x ∨ z = y ⟩
def is_associative [O : Operation α] := ∀ x y z, O.op x (O.op y z) = O.op (O.op x y) z
theorem is_associative_I [I : IOperation α] : @is_associative α (@instOperation α I) := by
/-
α : Type u_1
I : IOperation α
⊢ is_associative
-/
intro x y z
/-
α : Type u_1
I : IOperation α
x y z : α
⊢ Operation.op x (Operation.op y z) = Operation.op (Operation.op x y) z
-/
admit
Alex J. Best (Nov 11 2022 at 12:41):
One way is to use dsimp
, for instance
dsimp only [is_associative]
will work in your case
Pieter Cuijpers (Nov 11 2022 at 12:45):
Great, that indeed works well on the first step.
But to simplify the "Operation.op" after the intro, it's not so clear to me how I could use it?
dsimp [instOperation I] doesn't seem to help
Alex J. Best (Nov 11 2022 at 12:49):
dsimp [Operation.op, instOperation]
will unfold everything for the next step, then it gets a bit tricky because I don't quite understand what is being modelled!
Kevin Buzzard (Nov 11 2022 at 12:50):
PS #backticks (that's a link -- you can edit your first post if you like)
Pieter Cuijpers (Nov 11 2022 at 12:51):
Wonderful! Thanks a lot. I think I can manage what comes after that :-)
Pieter Cuijpers (Nov 11 2022 at 13:00):
Reading up a bit on dsimp https://leanprover-community.github.io/extras/simp.html I get the impression I should be careful using simp or dsimp "in the middle of a proof" except in specific cases. Your suggestion of dsimp only [...] is indicated as "safe", but I don't fully grasp the rationale behind these remarks yet. Is it because the execution of "simp" may change when theorems are added to it, so your proof might all of a sudden break if the context changes?
Kevin Buzzard (Nov 11 2022 at 13:01):
Yes that's it -- it's a PITA to have to fix up someone else's proof in your PR because you added some cool new simp
lemmas which broke someone else's poorly-written code.
Kevin Buzzard (Nov 11 2022 at 13:02):
If simp
works and makes progress but doesn't close a goal, you can replace it with squeeze_simp
and then click on the blue output which will replace again with simp only [list of lemmas]
which should hopefully work.
Yaël Dillies (Nov 11 2022 at 14:39):
Note that "non-terminal dsimp
" are very much accepted, because the goal after is guaranteed to be defeq to the goal after.
Mario Carneiro (Nov 11 2022 at 14:42):
well, rw
can still fail after a non-terminal dsimp
Yaël Dillies (Nov 11 2022 at 14:45):
Yes but that's much easier to fix than a non-terminal simp where you might get into a completely different goal.
Yaël Dillies (Nov 11 2022 at 14:46):
Our goal is not that no proof will ever break, right? That's unreachable. Our goal is that when a proof breaks it is fixable easily. And having a goal that's defeq to what it should be makes breakage easily fixable.
Mario Carneiro (Nov 11 2022 at 14:55):
I'm not sure it's true that defeq is any easier to fix than non-defeq when your goal looks completely different after a big simp
. I would say that it is only okay if the follow up tactic is not sensitive to the goal except up to defeq, e.g. if you use exact
/ refine
/ apply
/ change
Mario Carneiro (Nov 11 2022 at 14:55):
which is similar to the rule we have for nonterminal simp - it is okay as long as you follow up with a tactic that is not sensitive to details of the goal like ring
/ linarith
/ tidy
/ another simp
Last updated: Dec 20 2023 at 11:08 UTC