Zulip Chat Archive
Stream: mathlib4
Topic: !4#2894
Jeremy Tan (Mar 15 2023 at 04:17):
!4#2894 The mathlib3 code for the last function here works almost perfectly after correcting names. The exception is that Lean 4 cannot infer the instance CharP R p
for the last few lines despite it already being encoded as a hypothesis hp
(Lean 3 can). How can I "extract" the instance from the hypothesis?
theorem expChar_is_prime_or_one (q : ℕ) [hq : ExpChar R q] : Nat.Prime q ∨ q = 1 :=
or_iff_not_imp_right.mpr fun h => by
cases' CharP.exists R with p hp
-- ...
have p_eq_q : p = q := (char_eq_expChar_iff R p q).mpr (char_prime_of_ne_zero R p_ne_zero)
cases' CharP.char_is_prime_or_zero R p with pprime
· rwa [p_eq_q] at pprime
· contradiction
I have provisionally included CharP R p
up top as an explicit instance to illustrate my point
Jeremy Tan (Mar 15 2023 at 04:22):
Trying to apply what I learned from !4#2813
Eric Wieser (Mar 15 2023 at 08:28):
I would guess etaExperiment
might be relevant here
Jeremy Tan (Mar 15 2023 at 08:52):
Eric Wieser said:
I would guess
etaExperiment
might be relevant here
tried that, doesn't change anything, still errors out
Oliver Nash (Mar 15 2023 at 09:52):
Thanks for working on this. I just had a quick look and I think the issue was that we don't have casesI
(yet?). I pushed a commit which I believe should fix the build.
Eric Wieser (Mar 15 2023 at 09:57):
Am I imagining that Lean 4 did away with the instance cache and that therefore casesI isn't needed?
Jeremy Tan (Mar 15 2023 at 10:00):
Oliver Nash said:
Thanks for working on this. I just had a quick look and I think the issue was that we don't have
casesI
(yet?). I pushed a commit which I believe should fix the build.
oh, I didn't know haveI
existed in Lean 4 at all, thanks
Yaël Dillies (Mar 15 2023 at 10:00):
Lean 4's haveI
does not mean the same thing as Lean 3's haveI
Mario Carneiro (Mar 15 2023 at 10:16):
Eric Wieser said:
Am I imagining that Lean 4 did away with the instance cache and that therefore casesI isn't needed?
Yes to the second part, no to the first. Lean 4 didn't do away with the instance cache, it now effectively calls resetI
whenever the local context changes at all. Some internals had to be changed to make this performant enough
Eric Wieser (Mar 15 2023 at 10:17):
Yaël Dillies said:
Lean 4's
haveI
does not mean the same thing as Lean 3'shaveI
Can you elaborate on this?
Ruben Van de Velde (Mar 15 2023 at 10:18):
It's now "I" for "inline" rather than "instance cache". I still don't know what that means in practice
Notification Bot (Mar 15 2023 at 10:24):
12 messages were moved from this topic to #mathlib4 > tactic documentation by Eric Wieser.
Mario Carneiro (Mar 15 2023 at 10:28):
The difference is that have x : Nat := 0; exact Nat.succ x
expands to (fun x => Nat.succ x) 0
while haveI x : Nat := 0; exact Nat.succ x
expands to Nat.succ 0
Kevin Buzzard (Mar 15 2023 at 11:43):
so lean 3 tactic let
is lean 4 have
? I hadn't realised this.
Kevin Buzzard (Mar 15 2023 at 11:46):
@Oliver Nash it seems that have : CharP R p := hp
also works! I find this quite bizarre -- the claim seems to be that now Lean 4 doesn't need lean 3 haveI
because the cache is reset, but the PR in its broken state before you inserted the haveI line seems to be an explicit counterexample to this. We have hp
explicitly in the local context and the have
line just adds it a second time, which magically fixes all the problems. This looks to me like a bug in the instance cache generation system?
Mario Carneiro (Mar 15 2023 at 11:58):
Kevin Buzzard said:
so lean 3 tactic
let
is lean 4have
? I hadn't realised this.
No, let
and have
are still different and the distinction is the same as in lean 3
Mario Carneiro (Mar 15 2023 at 11:59):
the only difference with haveI
is the resulting term after elaboration. You still cannot make use of a defeq x = 0
after haveI x := 0
Mario Carneiro (Mar 15 2023 at 12:00):
The behavior you describe sounds like an instability in the instance search mechanism, e.g. putting it last makes it take a different path
Eric Rodriguez (Mar 15 2023 at 13:33):
Kevin Buzzard said:
so lean 3 tactic
let
is lean 4have
? I hadn't realised this.
I think the confounding thing is that there's two different have
s in Lean3 - have
in tactic mode, iirc, does just do the inlining process that Lean4 haveI
does. However, there's a _term-mode_ have
which is different, and is like lean4's have
tactic.
Kyle Miller (Mar 15 2023 at 14:20):
Huh, I'd never realized this about Lean 3's have
tactic. I'd always thought it worked just the same way as the have
expression, but I'd never checked.
Lean 3:
def foo'' : ℕ :=
begin
have n : ℕ := 2,
have n' := n + n,
have n'' := n' + n',
have n''' := n'' + n'',
exact n'''
end
#print foo''
-- def foo'' : ℕ :=
-- 2 + 2 + (2 + 2) + (2 + 2 + (2 + 2))
Lean 4:
def foo'' : Nat := by
have n : Nat := 2
have n' := n + n
have n'' := n' + n'
have n''' := n'' + n''
exact n'''
#print foo''
/-
def foo'' : Nat :=
let_fun n := 2;
let_fun n' := n + n;
let_fun n'' := n' + n';
let_fun n''' := n'' + n'';
n'''
-/
(let_fun x := v; w
is syntactic sugar for (fun x => w) v
)
Kevin Buzzard (Mar 15 2023 at 14:39):
Mario Carneiro said:
Eric Wieser said:
Am I imagining that Lean 4 did away with the instance cache and that therefore casesI isn't needed?
Yes to the second part, no to the first. Lean 4 didn't do away with the instance cache, it now effectively calls
resetI
whenever the local context changes at all. Some internals had to be changed to make this performant enough
So is the following a bug?
import Mathlib.Tactic.Cases
class Foo (T : Type) : Prop where
theorem exists_foo : ∃ T, Foo T := sorry
example : False := by
cases' exists_foo with T hT
-- `hT : Foo T`
-- have : Foo T := inferInstance -- fails
have : Foo T := hT
have : Foo T := inferInstance
sorry
Adam Topaz (Mar 15 2023 at 15:02):
I would guess that this is a bug with cases'
but I can't say for sure. Of course, Mario will be able to tell immediately.
Kyle Miller (Mar 15 2023 at 15:03):
This seems to affect cases
too:
class Foo (T : Type) : Prop where
theorem exists_foo : ∃ T, Foo T := sorry
example : False := by
cases exists_foo
rename_i T hT
have : Foo T := hT -- delete to get error in next line
have : Foo T := inferInstance
sorry
Adam Topaz (Mar 15 2023 at 15:04):
both rcases
and obtain
work perfectly fine.
Mario Carneiro (Mar 15 2023 at 15:18):
Based on this evidence I would guess cases
is at fault. rcases
is most likely saved because it constructs some intermediates using have
Floris van Doorn (Mar 15 2023 at 17:19):
Together with @Kyle Miller I figured out what causes this.
cases
andcases'
both call docs#Lean.MVarId.introNintroN
(viaintroNImp
) calls docs4#Lean.Meta.withNewLocalInstances that checks whether certain fvars are classes using two methodsisClassQuick?
andisClassExpensive?
. These two functions both have some support dealing with metavariables, but it makes the wrong decision in certain cases, not recognizing thatFoo T
is a class in Kyle's latest example. We tested that this fix fixes Kyle's latest example. Is a PR with this change welcome?
Scott Morrison (Mar 19 2023 at 23:15):
Seems like it would be worth making a PR with this fix. It may sit on the queue for a little while still.
Last updated: Dec 20 2023 at 11:08 UTC