Zulip Chat Archive
Stream: new members
Topic: Efficiently unfolding notation
Keefer Rowan (May 16 2020 at 12:18):
How is one supposed to unfold notation that comes from type classes? E.g. :
theorem not_mem_mem_compl {α : Type u} (x : α) (S : set α) (h : ¬ (x ∈ S)) : x ∈ (- S) :=
begin
sorry
end
I want to be able to unfold the notation -S
using the definition of compl
, so I would write unfold compl
. This doesn't work, as I need to also tell it to unfold has_neg.neg
, as the -
notation is given for compl as an instance of the type class has_neg
. Is there a better way to do this than unfold has_neg.neg compl
? I want to be able to think of the notation as an abbreviation for compl
, but here it is demanding an extra step. It doesn't seem similar steps are necessary for the notation +
on nat
, which is introduced the same way, with has_add
. Is there an attribute I can give something so that unfold
knows to incorporate has_neg
?
Reid Barton (May 16 2020 at 12:19):
Three backticks and then a newline
Keefer Rowan (May 16 2020 at 12:20):
Thanks, fixed it.
Reid Barton (May 16 2020 at 12:20):
I think you also need these two steps to unfold +
on nats, no?
Reid Barton (May 16 2020 at 12:20):
Or maybe the difference is +
has an equational lemma which is phrased in terms of the notation?
Reid Barton (May 16 2020 at 12:21):
Because you probably only want to unfold +
when you're also applying one of the two defining equations.
Keefer Rowan (May 16 2020 at 12:21):
Why does this work?
example : (1 + 0 = 1):=
begin
refl,
end
Reid Barton (May 16 2020 at 12:21):
Because refl
works up to definitional equality
Reid Barton (May 16 2020 at 12:22):
Er, well okay the exact reason is a bit complicated
Reid Barton (May 16 2020 at 12:22):
If you said exact rfl
, then the reason would be that exact
works up to definitional equality
Keefer Rowan (May 16 2020 at 12:22):
How does refl
know to access has_add.add
while unfold
and dunfold
doesn't?
Reid Barton (May 16 2020 at 12:23):
refl
doesn't know anything about has_add
Reid Barton (May 16 2020 at 12:23):
refl
says: the goal is equality, so I'll supply eq.rfl
as the proof term
Reid Barton (May 16 2020 at 12:23):
and eq.rfl : 1 + 0 = 1
, so Lean is happy
Reid Barton (May 16 2020 at 12:25):
In order to check this eq.rfl : 1 + 0 = 1
, Lean knows that +
is notation for has_add.add
and it knows how to reduce has_add.add
applied to the has_add
instance for nat
to get nat.add
, and then how to unfold nat.add
to its definition in terms of nat.rec
, and then how to reduce nat.rec
applied to 0
, etc. But this is all happening outside the tactic layer.
Reid Barton (May 16 2020 at 12:25):
On the other hand, unfold
means: replace the named thing with its definition (possibly applying equational lemmas).
Reid Barton (May 16 2020 at 12:26):
You didn't give an example involving +
and unfold
, so it's not analogous.
Keefer Rowan (May 16 2020 at 12:26):
So in some sense refl
is "smarter" or has access to more stuff than unfold' (but as you say it's all happening outside of tactic layer). So
refl can figure out definitions that
unfold` can't without being fed them explicitly?
Reid Barton (May 16 2020 at 12:27):
If anything, refl
is dumber.
Reid Barton (May 16 2020 at 12:27):
There are several layers at work here, and several different notions of equality.
Keefer Rowan (May 16 2020 at 12:28):
And your point about not having an example of +
and unfold
is fair; you made me realize why I thought you didn't need the two unfolding steps for nat
, which was wrong, but that led to the question about refl
.
Reid Barton (May 16 2020 at 12:28):
If you don't mind, whenever you say refl
, I'll pretend you said exact rfl
, since that cuts out an irrelevant step (deciding which kind of reflexivity to use).
Keefer Rowan (May 16 2020 at 12:29):
I think I'm getting the general picture now. My final question about this topic is how you would prove the (trivial) theorem above:
theorem not_mem_mem_compl {α : Type u} (x : α) (S : set α) (h : ¬ (x ∈ S)) : x ∈ (- S)
Reid Barton (May 16 2020 at 12:29):
exact
is a tactic that uses the term you give it to close the goal. The term only has to match the goal up to definitional equality, which means up to unfolding anything that needs unfolding.
Keefer Rowan (May 16 2020 at 12:30):
Noting that
def compl (s : set α) : set α :=
{a | a ∉ s}
Reid Barton (May 16 2020 at 12:30):
Well, one way is just := h
Reid Barton (May 16 2020 at 12:31):
or := by exact h
--this takes advantage of definitional equality
Keefer Rowan (May 16 2020 at 12:31):
Ok, because everything holds definitionally, exact can figure it out.
Reid Barton (May 16 2020 at 12:31):
alternatively, there is probably already a lemma which says precisely this
Reid Barton (May 16 2020 at 12:31):
Probably named something like mem_compl
or mem_compl_iff
Reid Barton (May 16 2020 at 12:32):
Using that is better practice in principle, since it insulates you from the specific definition of compl
Keefer Rowan (May 16 2020 at 12:32):
Yeah, I just wanted an example. Thanks for your help! I think (most of) my confusion has been resolved. And your last comment makes sense.
Kevin Buzzard (May 16 2020 at 12:59):
In the natural number game, zero_add
is a theorem which is proved by induction, but add_zero
can be proved by refl
. Definitional equality is not mathematical, in some sense; it depends on exactly how an object is defined, rather than the way a mathematician thinks about it (where there might be several different definitions of one thing, all equivalent).
Last updated: Dec 20 2023 at 11:08 UTC