Zulip Chat Archive
Stream: Is there code for X?
Topic: making implicit variable explicit in output
Filippo A. E. Nuccio (Apr 25 2022 at 18:18):
When applying a certain lemma (notably docs#finset.le_max'), the conclusion contains and underscore that I can't turn into something more explicit. My question is not about these finset.max'
issues, but about the underscore, it just so happens that I met the problem while playing with finsets. A MWE is the following
import tactic
open finset
example (A : finset ℕ) (H : finset.nonempty A) (a B : ℕ) (ha : a ∈ A) (hB : B = A.max' H) :
a ≤ B.succ :=
begin
have one := A.le_max' a ha,
have two := nat.le_succ (A.max' H),
have three := one.trans two,
rwa [← hB] at three,
end
which works, but
import tactic
open finset
example (A : finset ℕ) (H : finset.nonempty A) (a B : ℕ) (ha : a ∈ A) (hB : B = A.max' H) :
begin
a ≤ B.succ :=
have := (A.le_max' a ha).trans (nat.le_succ (A.max' H)),
rw [← hB] at this, -- rewrite tactic failed, did not find instance of the pattern in the target expression
--A.max' H
end
does not (if I replace rw [← hB] at this
by erw [← hB] at this,
everything is fine, but that is not the point of my question). The funny thing is that in the first example, after introducing one
and two
, their transitive composition is three : a ≤ (A.max' H).succ
whereas in the second example the "direct" transitive composition is this : a ≤ (A.max' _).succ
.
So my questions are
- Is there a way to force Lean to remember what the underscore was even if the conclusion of the
lemma
contains a_
? - Why is the transitive composition of
one
andtwo
rememberingH
, whereas the direct composition does not? - Is there a reason why in
mathlib
we prefer (if I undestand correctly) the version of the lemma with the_
?
Reid Barton (Apr 25 2022 at 18:38):
It's not really an "underscore" in finset.le_max'
, the documentation generator is just printing it that way for some reason.
Reid Barton (Apr 25 2022 at 18:38):
Does rw
not understand definitional proof irrelevance?
Reid Barton (Apr 25 2022 at 18:39):
You should probably write an expected type on the have
(involving H
), then the rw
works fine
Patrick Johnson (Apr 25 2022 at 18:45):
- Is there a way to force Lean to remember what the underscore was even if the conclusion of the
lemma
contains a_
?
Underscore is not a thing in the type theory. It's just a pretty-print feature that hides complicated proofs (because of proof irrelevance). Lean knows how each underscore is constructed and you can extract a proof as an assumption using generalize_proofs
tactic. You can either do
have : a ≤ (A.max' H).succ := (A.le_max' a ha).trans (nat.le_succ (A.max' H)),
rw ←hB at this,
or
have := (A.le_max' a ha).trans (nat.le_succ (A.max' H)),
generalize_proofs at this,
rw ←hB at this,
Filippo A. E. Nuccio (Apr 25 2022 at 18:50):
Thanks!
Riccardo Brasca (Apr 25 2022 at 18:56):
Does set_option pp.proofs true
help?
Patrick Johnson (Apr 25 2022 at 19:09):
- Why is the transitive composition of
one
andtwo
rememberingH
, whereas the direct composition does not?
The underscore from A.le_max' a ha
is Exists.intro a ha
, which is definitionally equal to the proof of A.nonempty
(because ∃ (x : ℕ), x ∈ A
is definitionally equal to A.nonempty
).
When you write have two := nat.le_succ (A.max' H)
, the type includes H
because you explicitly used H
to construct the proof. On the other hand, when you write have three := (A.le_max' a ha).trans (nat.le_succ (A.max' H))
, the proof of H
gets unified with Exists.intro a ha
(because they are defeq). Since there is no (syntactically equal) proof of Exists.intro a ha
in the assumptions, it gets displayed as underscore and rw
gets confused.
Patrick Johnson (Apr 25 2022 at 19:21):
- Is there a reason why in
mathlib
we prefer (if I undestand correctly) the version of the lemma with the_
?
finset.le_max'
could be defined in a slightly different way to avoid underscores:
lemma finset.le_max' {α : Sort*} [linear_order α] (s : finset α) (x : α) (h : x ∈ s) :
∃ h₁, x ≤ s.max' h₁ :=
Exists.intro ⟨_, h⟩ (le_max_of_mem h (option.get_mem _))
Use it with (A.le_max' a ha).some_spec
Yaël Dillies (Apr 25 2022 at 19:26):
This cause problem in Lean 3 however because we don't have eta expansion.
Yaël Dillies (Apr 25 2022 at 19:28):
No, I am not making sense.
Yaël Dillies (Apr 25 2022 at 19:30):
What about using a default argument?
lemma le_max' {α : Type*} [linear_order α] (s : finset α) (x : α) (hx : x ∈ s)
(h : s.nonempty := ⟨x, hx⟩) :
x ≤ s.max' h := sorry
Reid Barton (Apr 25 2022 at 19:34):
What's the rationale for rw
not working in the second example considering that the types match up to definitional proof irrelevance?
Reid Barton (Apr 25 2022 at 19:35):
Is it that rw
might want to inspect the proof argument to infer the values of some non-propositional variables?
Reid Barton (Apr 25 2022 at 19:36):
Would it make sense for rw
to treat the proof as irrelevant as a fallback option?
Patrick Johnson (Apr 25 2022 at 19:51):
Simplified example:
import data.finset.basic
example {α : Type} {s : finset α} {f : s.nonempty → ℕ}
{h₁ : s.nonempty}
{h₂ : ∃ (a : α), a ∈ s}
(h₃ : f h₁ = 0) :
f h₂ = 0 :=
begin
rw h₃, -- fails
end
Seems like rw
does not unfold finset.nonempty
Reid Barton (Apr 25 2022 at 19:52):
That's interesting and not what I thought was happening but, in some ways, leaves me more confused!
Reid Barton (Apr 25 2022 at 19:53):
Namely, it does work with h₂ : s.nonempty
instead
Filippo A. E. Nuccio (Apr 26 2022 at 07:19):
Very interesting, thank you very much. I am not sure I fully understand your answer to point 2., but that is my lack of knowledge. I will read carefully and try to come back if I need further clarification. :working_on_it:
Filippo A. E. Nuccio (Apr 26 2022 at 07:29):
Riccardo Brasca said:
Does
set_option pp.proofs true
help?
No, unfortunately it does not, because with this option instead of
have := (A.le_max' a ha).trans (nat.le_succ (A.max' H)), -- a ≤ (A.max' _).succ
I find
have := (A.le_max' a ha).trans (nat.le_succ (A.max' H)), -- a ≤ (A.max' (Exists.intro a ha)).succ
which (much in the spirit of @Patrick Johnson 's suggestions) is not matched neither when doing rw ← hB
(for hB : B = A.max' H
).
Last updated: Dec 20 2023 at 11:08 UTC