Zulip Chat Archive
Stream: general
Topic: Tactic doesn't work in record syntax
Adam Topaz (Nov 25 2020 at 23:34):
Can anyone help me understand what's going on with the following code?
import algebra
import linear_algebra
import data.matrix.notation
variables (L : Type*) [field L] (V : Type*) [add_comm_group V] [vector_space L V]
@[ext]
structure nonzero_vectors :=
(to_vec : V)
(nonzero : to_vec ≠ 0)
lemma foo : ![(1 : L),0] ≠ 0 := by tidy -- this works...
example : nonzero_vectors (fin 2 → L) :=
{ to_vec := ![1,0],
nonzero := by tidy } -- this fails...
example : nonzero_vectors (fin 2 → L) :=
{ to_vec := ![1,0],
nonzero := foo _ } -- this works
tidy
very happily proves that is nonzero in the lemma foo
, but it doesn't work in the second example.
Kevin Buzzard (Nov 25 2020 at 23:39):
goodness knows whether this is relevant, but the infoview says that the first goal is about a map fin 1.succ → L
but the failure is about a map fin 2 → L
Kevin Buzzard (Nov 25 2020 at 23:41):
this is I think a red herring.
example : nonzero_vectors (fin (nat.succ 1) → L) :=
{ to_vec := ![1,0],
nonzero := by tidy } -- this still fails...
Kevin Buzzard (Nov 25 2020 at 23:43):
example : ![(1 : L),0] ≠ 0 := by tidy? -- intros ᾰ, simp at *, assumption
example : nonzero_vectors (fin 2 → L) :=
{ to_vec := ![1,0],
nonzero := by {intros x, simp at *, assumption} } -- simp fails...
Kenny Lau (Nov 25 2020 at 23:44):
https://www.diffchecker.com/xOMY4t91
Kenny Lau (Nov 25 2020 at 23:44):
the LHS is the version of ᾰ
that fails; RHS is the version that succeeds
Adam Topaz (Nov 25 2020 at 23:44):
It this supposed to be read by a human?
Kevin Buzzard (Nov 25 2020 at 23:44):
example : ![(1 : L),0] ≠ 0 := by { intros x, simp at x, assumption }
example : nonzero_vectors (fin 2 → L) :=
{ to_vec := ![1,0],
nonzero := by {intros x, simp at x, assumption} } -- simp fails...
Kevin Buzzard (Nov 25 2020 at 23:46):
example : ![(1 : L),0] ≠ 0 := begin
intros x,
simp only [one_ne_zero, matrix.cons_eq_zero_iff, false_and] at x,
assumption
end
example : nonzero_vectors (fin 2 → L) :=
{ to_vec := ![1,0],
nonzero := by {
intros x,
simp only [one_ne_zero, matrix.cons_eq_zero_iff, false_and] at x, -- fails
assumption} }
Kenny Lau (Nov 25 2020 at 23:46):
this is the diff when I use (nat.succ $ nat.succ 0)
: https://www.diffchecker.com/CR8HCTXs
Kenny Lau (Nov 25 2020 at 23:46):
the diff is smaller, but still exists
Adam Topaz (Nov 25 2020 at 23:46):
I don't think it's about the 2 in fin 2
. The second example works
Kevin Buzzard (Nov 25 2020 at 23:47):
Adam Topaz said:
It this supposed to be read by a human?
This is what kids who don't have diff
do.
Kenny Lau (Nov 25 2020 at 23:48):
example : ![(1 : L),0] ≠ 0 :=
begin
intros ᾰ,
rw [matrix.cons_eq_zero_iff] at ᾰ, -- works
end
example : nonzero_vectors (fin (nat.succ $ nat.succ 0) → L) :=
{ to_vec := ![1,0],
nonzero := begin
intros ᾰ,
rw [matrix.cons_eq_zero_iff] at ᾰ, -- fails
end
}
Adam Topaz (Nov 26 2020 at 00:10):
I think this is related:
import algebra
import linear_algebra
import data.matrix.notation
variables (L : Type*) [field L]
abbreviation bar : fin 2 → L := ![1,0]
lemma foo : bar L ≠ 0 := by tidy -- this works...
@[reducible]
def baz : fin 2 → L := ![1,0]
lemma foo' : baz L ≠ 0 := by tidy -- this works...
def baz' : fin 2 → L := ![1,0]
lemma foo'' : baz' L ≠ 0 := by tidy -- this fails...
Kevin Buzzard (Nov 26 2020 at 00:16):
Fixed it for you:
example : nonzero_vectors (fin (0 : ℕ).succ.succ → L) :=
{ to_vec := ![1,0],
nonzero := by {
intros x,
set goodzero :=
(@has_zero.zero.{0} (fin (nat.succ (nat.succ (@has_zero.zero.{0} nat nat.has_zero))) → L)
(@pi.has_zero.{0 0} (fin (nat.succ (nat.succ (@has_zero.zero.{0} nat nat.has_zero))))
(λ (ᾰ : fin (nat.succ (nat.succ (@has_zero.zero.{0} nat nat.has_zero)))), L)
(λ (i : fin (nat.succ (nat.succ (@has_zero.zero.{0} nat nat.has_zero)))),
@mul_zero_class.to_has_zero.{0} L
(@monoid_with_zero.to_mul_zero_class.{0} L
(@semiring.to_monoid_with_zero.{0} L
(@ring.to_semiring.{0} L
(@division_ring.to_ring.{0} L (@field.to_division_ring.{0} L _inst_1))))))))
with hgoodzero,
set badzero :=
(@has_zero.zero.{0} (fin (nat.succ (nat.succ (@has_zero.zero.{0} nat nat.has_zero))) → L)
(@add_monoid.to_has_zero.{0} (fin (nat.succ (nat.succ (@has_zero.zero.{0} nat nat.has_zero))) → L)
(@add_group.to_add_monoid.{0} (fin (nat.succ (nat.succ (@has_zero.zero.{0} nat nat.has_zero))) → L)
(@add_comm_group.to_add_group.{0} (fin (nat.succ (nat.succ (@has_zero.zero.{0} nat nat.has_zero))) → L)
(@pi.add_comm_group.{0 0} (fin (nat.succ (nat.succ (@has_zero.zero.{0} nat nat.has_zero))))
(λ (ᾰ : fin (nat.succ (nat.succ (@has_zero.zero.{0} nat nat.has_zero)))), L)
(λ (i : fin (nat.succ (nat.succ (@has_zero.zero.{0} nat nat.has_zero)))),
@ring.to_add_comm_group.{0} L
(@division_ring.to_ring.{0} L (@field.to_division_ring.{0} L _inst_1))))))))
with hbadzero,
have : badzero = goodzero := rfl,
rw this at x,
tidy } }
Kevin Buzzard (Nov 26 2020 at 00:17):
variables (L : Type) [field L] (V : Type) [add_comm_group V] [vector_space L V]
Reid Barton (Nov 26 2020 at 00:17):
Kevin, you're not supposed to write the name ᾰ
explicitly
Kevin Buzzard (Nov 26 2020 at 00:18):
That was Kenny! I'd never dream of doing that!
Kevin Buzzard (Nov 26 2020 at 00:19):
In fact the moment I saw his code I linted it, hoping that there was now an ᾰ
linter.
Kevin Buzzard (Nov 26 2020 at 00:19):
oh no crap I just saw it in mine too :-/ Who put that there?
Reid Barton (Nov 26 2020 at 00:20):
We really should have gone with something like :nuclear:
Kevin Buzzard (Nov 26 2020 at 00:21):
Patrick claimed recently that we didn't need pp.all
any more because the infoview would take care of everything, but it was very handy here. Of course I don't have a clue about the actual problem, namely that for some reason we have two different zeros.
Kevin Buzzard (Nov 26 2020 at 00:22):
Here's all the code. You can see after the two intros x
that the types are slightly different -- this was Kenny's observation.
import algebra
import linear_algebra
import data.matrix.notation
variables (L : Type) [field L] (V : Type) [add_comm_group V] [vector_space L V]
@[ext]
structure nonzero_vectors :=
(to_vec : V)
(nonzero : to_vec ≠ 0)
set_option pp.all true
example : ![(1 : L),0] ≠ 0 := begin
intros x,
rw matrix.cons_eq_zero_iff at x,
simp only [one_ne_zero, matrix.cons_eq_zero_iff, false_and] at x,
assumption
end
example : nonzero_vectors (fin (0 : ℕ).succ.succ → L) :=
{ to_vec := ![1,0],
nonzero := by {
intros x,
set goodzero :=
(@has_zero.zero.{0} (fin (nat.succ (nat.succ (@has_zero.zero.{0} nat nat.has_zero))) → L)
(@pi.has_zero.{0 0} (fin (nat.succ (nat.succ (@has_zero.zero.{0} nat nat.has_zero))))
(λ (ᾰ : fin (nat.succ (nat.succ (@has_zero.zero.{0} nat nat.has_zero)))), L)
(λ (i : fin (nat.succ (nat.succ (@has_zero.zero.{0} nat nat.has_zero)))),
@mul_zero_class.to_has_zero.{0} L
(@monoid_with_zero.to_mul_zero_class.{0} L
(@semiring.to_monoid_with_zero.{0} L
(@ring.to_semiring.{0} L
(@division_ring.to_ring.{0} L (@field.to_division_ring.{0} L _inst_1))))))))
with hgoodzero,
set badzero :=
(@has_zero.zero.{0} (fin (nat.succ (nat.succ (@has_zero.zero.{0} nat nat.has_zero))) → L)
(@add_monoid.to_has_zero.{0} (fin (nat.succ (nat.succ (@has_zero.zero.{0} nat nat.has_zero))) → L)
(@add_group.to_add_monoid.{0} (fin (nat.succ (nat.succ (@has_zero.zero.{0} nat nat.has_zero))) → L)
(@add_comm_group.to_add_group.{0} (fin (nat.succ (nat.succ (@has_zero.zero.{0} nat nat.has_zero))) → L)
(@pi.add_comm_group.{0 0} (fin (nat.succ (nat.succ (@has_zero.zero.{0} nat nat.has_zero))))
(λ (ᾰ : fin (nat.succ (nat.succ (@has_zero.zero.{0} nat nat.has_zero)))), L)
(λ (i : fin (nat.succ (nat.succ (@has_zero.zero.{0} nat nat.has_zero)))),
@ring.to_add_comm_group.{0} L
(@division_ring.to_ring.{0} L (@field.to_division_ring.{0} L _inst_1))))))))
with hbadzero,
have : badzero = goodzero := rfl,
rw this at x,
tidy } }
Kenny Lau (Nov 26 2020 at 00:24):
Kevin Buzzard said:
this was Kenny's observation
This sounds like research-paper language to me
Adam Topaz (Nov 26 2020 at 00:25):
$$\text{[5] K. Lau, \emph{Private communication} (2020).}$$
Adam Topaz (Nov 26 2020 at 00:26):
fail
Adam Topaz (Nov 26 2020 at 00:26):
So do I understand correctly that the issue is with the 0
in \neq 0
?
Kevin Buzzard (Nov 26 2020 at 00:28):
Yes that's my understanding too -- the RHS zeros are for some reason different.
Adam Topaz (Nov 26 2020 at 00:32):
This is less than ideal, but it works :expressionless:
import algebra
import linear_algebra
import data.matrix.notation
variables (L : Type*) [field L]
@[ext]
structure nonzero_vectors (n : ℕ) :=
(to_vec : fin n → L)
(nonzero : to_vec ≠ 0)
lemma foo : ![(1 : L),0] ≠ 0 := by tidy -- this works...
example : nonzero_vectors L 2 :=
{ to_vec := ![1,0],
nonzero := by tidy }
Adam Topaz (Nov 26 2020 at 00:32):
Even better:
import algebra
import linear_algebra
import data.matrix.notation
variables (L : Type*) [field L]
@[ext]
structure nonzero_vectors (n : ℕ) :=
(to_vec : fin n → L)
(nonzero : to_vec ≠ 0 . obviously)
example : nonzero_vectors L 2 := ⟨![1,0]⟩
Kevin Buzzard (Nov 26 2020 at 00:33):
why are these things working but other things aren't working?
Adam Topaz (Nov 26 2020 at 00:33):
¯\_(ツ)_/¯
Adam Topaz (Nov 26 2020 at 00:44):
import algebra
import linear_algebra
import data.matrix.notation
variables (L : Type*) [field L]
local attribute [reducible] has_zero.zero
@[ext]
structure nonzero_vectors (V : Type*) [add_comm_group V] [vector_space L V] :=
(to_vec : V)
(nonzero : to_vec ≠ 0)
example : nonzero_vectors L (fin 2 → L) :=
{ to_vec := ![1,0],
nonzero := begin
change _ ≠ 0, -- fail!?
end}
Adam Topaz (Nov 26 2020 at 00:45):
The change
line fails. not definitionally equal
Kevin Buzzard (Nov 26 2020 at 00:48):
So I guess what's happening is that when you make the structure
variables (L : Type) [field L] (V : Type) [add_comm_group V] [vector_space L V]
structure nonzero_vectors :=
(to_vec : V)
(nonzero : to_vec ≠ 0)
the zero is coming from the fact that V is an add_comm_group
. But here
example : ![(1 : L),0] ≠ 0 := begin
...
Lean knows that the vector space is fin 2 -> L
and whilst this is an add_comm_group, the zero comes from pi.has_zero
. These things are defeq so there are no diamond problems, but the problem is that the solution found by simp
involves matrix.cons_eq_zero_iff
which has the pi.has_zero
zero. The rewrite shouldn't fail because the zeros are defeq, but for some reason it does fail -- this is not the first time I have seen rewrite failing under suspicious circumstances recently. Has there been a regression or something? Or am I talking nonsense?
Adam Topaz (Nov 26 2020 at 00:49):
I assume It doesn'terw
would work.
Adam Topaz (Nov 26 2020 at 00:51):
But yes, that sounds like a reasonable conclusion.
Adam Topaz (Nov 26 2020 at 00:52):
But this doesn't really explain why change
doesn't work.
Kevin Buzzard (Nov 26 2020 at 09:41):
The change
fails because that 0
is 0 : nat
. change
doesn't try to do any unification with the goal, it's much more stupid than that. It interprets what you give it and then unifies afterwards.
Adam Topaz (Nov 26 2020 at 14:02):
Oh, right. I figured lean would be smart enough to replace 0
with has_zero.zero
, but I guess not.
Kevin Buzzard (Nov 26 2020 at 15:22):
It's all about when elaboration happens I guess -- this is just something I've picked up over time. Before it attempts the change it decides it wants to figure out the type of 0
and because it doesn't have any other info, it goes for nat
, and from then on we're doomed.
Adam Topaz (Nov 26 2020 at 15:30):
I'm still a little puzzled as to why foo0 works but not foo:
import algebra
import linear_algebra
import data.matrix.notation
variables (L : Type*) [field L]
lemma foo0 : ![(1 : L),0,0,0,0,0] ≠ 0 := by tidy
lemma foo {n} (v : fin n → L) : ![1,v] ≠ 0 :=
begin
tidy,
sorry,
end
Kevin Buzzard (Nov 26 2020 at 15:32):
Oh I don't think we've got to the bottom of this! I still don't understand why the rewrite fails.
Adam Topaz (Nov 26 2020 at 15:33):
To un-#xy things, I'm trying to mimic a (fairly technical) argument using classical projective spaces (i.e. projectivization of (fin n \to L)
), so I'm happy to restrict myself to those vector spaces, at least for now.
Kevin Buzzard (Nov 26 2020 at 15:35):
I think tidy
made a wrong turn in the foo proof above. If n=0
then probably the goal isn't solvable after tidy
.
Adam Topaz (Nov 26 2020 at 15:35):
Note:
lemma foo {n} (v : fin n → L) : (matrix.vec_cons 1 v) ≠ 0 :=
begin
tidy, -- works
end
Reid Barton (Nov 26 2020 at 15:36):
I would definitely suggest not using tidy
as your proof when trying to debug something like this unless the problem is tidy
-specific
Kevin Buzzard (Nov 26 2020 at 15:37):
oh it's nothing to do with tidy
-- ![1,v]
is being interpreted as two terms of type fin n -> F
in the failing proof. foo
isn't true I suspect.
Reid Barton (Nov 26 2020 at 15:38):
right, because n
could be 0
Adam Topaz (Nov 26 2020 at 15:38):
But this fails:
lemma foo' {n} (v : fin n → L) : (fin.cons (1 : L) v : fin (n+1) → L) ≠ 0 :=
begin
tidy,
end
Adam Topaz (Nov 26 2020 at 15:40):
And @Reid Barton I agree that we should not be using tidy, but the main thing I'm trying to accomplish with this is to have some (however rudimentary) automation for proving vectors are nonzero, so that working with projective spaces isn't as awful, and tidy seems like the best choice.
Reid Barton (Nov 26 2020 at 15:40):
Right but if there's some obscure elaboration issue going on, then getting rid of mysterious gadgets like tidy
is the first step
Reid Barton (Nov 26 2020 at 15:41):
if tidy
does the same thing in the working and non-working cases, study that thing
Adam Topaz (Nov 26 2020 at 15:41):
tidy
isn't mysterious in this case. It just does intros a, simp at *, assumption
Reid Barton (Nov 26 2020 at 15:41):
if it does different things, then there's your problem
Reid Barton (Nov 26 2020 at 15:41):
great, so get rid of tidy
asap
Adam Topaz (Nov 26 2020 at 15:41):
and the simp at *
fails for the second one.
Adam Topaz (Nov 26 2020 at 15:42):
Looks like it has to do with matrix.cons_eq_zero_iff
Adam Topaz (Nov 26 2020 at 15:42):
So lean can't unify the fin.cons
with matrix.vec_cons
, I guess?
Reid Barton (Nov 26 2020 at 15:42):
and then try to figure out whether it's simp
not trying to apply the lemma, or whether rw
won't do it either, or whether explicitly using the lemma also fails, etc
Reid Barton (Nov 26 2020 at 15:42):
it sounds like you've already done this
Kenny Lau (Nov 26 2020 at 15:53):
Kenny Lau said:
example : ![(1 : L),0] ≠ 0 := begin intros ᾰ, rw [matrix.cons_eq_zero_iff] at ᾰ, -- works end example : nonzero_vectors (fin (nat.succ $ nat.succ 0) → L) := { to_vec := ![1,0], nonzero := begin intros ᾰ, rw [matrix.cons_eq_zero_iff] at ᾰ, -- fails end }
I already extracted the crucial component
Adam Topaz (Nov 26 2020 at 16:03):
Playing a bit more with @Kenny Lau 's examples:
import algebra
import linear_algebra
import data.matrix.notation
variables (L : Type*) [field L] (V : Type*) [add_comm_group V] [vector_space L V]
@[ext]
structure nonzero_vectors :=
(to_vec : V)
(nonzero : to_vec ≠ 0)
example : ![(1 : L),0] ≠ 0 :=
begin
intros a,
rw [matrix.cons_eq_zero_iff] at a, -- works
finish,
end
example : nonzero_vectors (fin 2 → L) :=
{ to_vec := ![1,0],
nonzero := begin
intros a,
-- "a : ![1,0] = 0" in context
change _ = (0 : fin 2 → L) at a,
-- "a : ![1,0] = 0" in context
rw [matrix.cons_eq_zero_iff] at a, --works
finish,
end
}
example : nonzero_vectors (fin 2 → L) :=
{ to_vec := ![1,0],
nonzero := begin
intros a,
erw [matrix.cons_eq_zero_iff] at a, --fails
sorry,
end
}
Adam Topaz (Nov 26 2020 at 16:11):
Here's a slightly more minimised version:
import algebra
import linear_algebra
import data.matrix.notation
variables (L : Type*) [field L] (V : Type*) [add_comm_group V] [vector_space L V]
@[ext]
structure zero_vectors :=
(to_vec : V)
(foo : to_vec = 0)
example : zero_vectors (fin 1 → L) :=
{ to_vec := ![0],
foo := begin
erw matrix.cons_eq_zero_iff, -- fails
end }
example : zero_vectors (fin 1 → L) :=
{ to_vec := ![0],
foo := begin
change _ = (0 : fin 1 → L),
rw matrix.cons_eq_zero_iff, -- works
finish,
end }
Adam Topaz (Nov 26 2020 at 16:22):
Okay, I think I'm starting to understand the issue here...
example : (![0] : fin 1 → L) = 0 := by refl -- fails
example : (![0] : fin 1 → L) = 0 :=
begin
rw matrix.cons_eq_zero_iff,
split,
refl,
rw eq_iff_true_of_subsingleton,
tauto,
end
Adam Topaz (Nov 26 2020 at 16:23):
Where is has_zero (fin n \to L)
defined?
Adam Topaz (Nov 26 2020 at 16:23):
Adam Topaz (Nov 26 2020 at 16:33):
Well.... I don't know. I think for now I'll just hack it like this:
import algebra
import linear_algebra
import data.matrix.notation
variables (L : Type*) [field L] (V : Type*) [add_comm_group V] [vector_space L V]
@[ext]
structure zero_vectors :=
(to_vec : V)
(foo : to_vec = 0 . obviously)
@[simp] lemma zero_eq {n} {α : Type*} [has_zero α] :
(0 : fin (n + 1) → α) = matrix.vec_cons (0 : α) 0 := by tidy
example : zero_vectors (fin 1 → L) := { to_vec := ![0] }
Adam Topaz (Nov 26 2020 at 16:39):
Unfortunately, this hack doesn't work for nonzero_vectors
.
Kevin Buzzard (Nov 27 2020 at 18:11):
import data.matrix.notation
variables (L : Type*) [field L] (V : Type*) [add_comm_group V] [vector_space L V]
@[ext]
structure nonzero_vectors :=
(to_vec : V)
(nonzero : to_vec ≠ 0)
example : ![(1 : L),0] ≠ 0 := begin
intros h,
-- rw matrix.cons_eq_zero_iff at h, -- works
simpa using h, -- uses `matrix.cons_eq_zero_iff`
end
example : nonzero_vectors (fin 2 → L) :=
{ to_vec := ![1,0],
nonzero := begin
intros h,
-- rw matrix.cons_eq_zero_iff at h, -- fails
-- rw @matrix.cons_eq_zero_iff L _ at h, -- fails
rw @matrix.cons_eq_zero_iff L _ _ at h, -- works, presumably because Lean uses L's zero finally
simpa using h,
end }
Adam Topaz (Nov 27 2020 at 19:09):
import data.matrix.notation
variables (L : Type*) [field L] (V : Type*) [add_comm_group V] [vector_space L V]
@[ext]
structure nonzero_vectors :=
(to_vec : V)
(nonzero : to_vec ≠ 0)
open matrix
@[simp] lemma cons_eq_zero_iff' {n} {α} [has_zero α] {v : fin n → α} {x : α} :
vec_cons x v = (λ _, 0) ↔ x = 0 ∧ v = 0 := cons_eq_zero_iff
example : nonzero_vectors (fin 2 → L) :=
{ to_vec := ![1,0],
nonzero := begin
intros h,
--erw cons_eq_zero_iff at h, -- fails
--rw cons_eq_zero_iff' at h, -- fails
erw cons_eq_zero_iff' at h, -- works
simpa using h,
end }
Kevin Buzzard (Nov 27 2020 at 19:10):
My mental model of erw
is "like rw
, but tries harder to unify". However my mental model of what is actually going on with unification is poor.
Kevin Buzzard (Nov 27 2020 at 19:12):
simp only [cons_eq_zero_iff'] at h,
fails. We need esimp
(and esimpa
)
Adam Topaz (Nov 27 2020 at 19:13):
Is it obvious what needs to be changed in cons_eq_zero_iff'
to make rw
work as opposed to erw
? I think when rw
works, then simp
can apply it, but that's not the case with erw
.
Kevin Buzzard (Nov 27 2020 at 19:14):
The "mistake" is not made by the lemma, my understanding of the issue is that unification has chosen a rather exotic zero for the right hand side of h
, so somehow it's not the lemma's fault that we have to resort to eew
Kevin Buzzard (Nov 27 2020 at 19:15):
or whatever it's called
Kevin Buzzard (Nov 27 2020 at 19:18):
Adam Topaz (Nov 27 2020 at 19:19):
Isn't there some way to write a simp lemma that would allow us to solve nonzero
in the example with by tidy
?
Adam Topaz (Nov 27 2020 at 19:19):
I was hoping cons_eq_zero_iff'
would do it, but no.
Kevin Buzzard (Nov 27 2020 at 19:20):
Oh I understand now, you're really trying to emulate the pi zero.
Kevin Buzzard (Nov 27 2020 at 19:21):
replace h := cons_eq_zero_iff'.1 h,
now works, but apparently this isn't good enough for rw
. (oh -- the point is that not even this works with cons_eq_zero_iff
-- I thought I'd posted some replace code but I ended up getting rw @ to work)
Kevin Buzzard (Nov 27 2020 at 19:24):
There's a way of turning on some trace messages so you can see exactly why it's failing...
Kevin Buzzard (Nov 27 2020 at 19:25):
Kevin Buzzard (Nov 27 2020 at 19:27):
set_option trace.type_context.is_def_eq true
set_option trace.type_context.is_def_eq_detail true
and then you can try and figure out why the rewrite is failing. I think.
Adam Topaz (Nov 27 2020 at 19:29):
Trace message
Kevin Buzzard (Nov 27 2020 at 19:37):
With erw
the trace indicates success here:
...
[type_context.is_def_eq_detail] [13]: 0 =?= field.zero
[type_context.is_def_eq_detail] [14]: has_zero.zero =?= field.zero
[type_context.is_def_eq_detail] on failure: has_zero.zero =?= field.zero
[type_context.is_def_eq_detail] on failure: 0 =?= field.zero
[type_context.is_def_eq_detail] synthesized instances on left
[type_context.is_def_eq_detail] [14]: 0 =?= field.zero
[type_context.is_def_eq_detail] [15]: mul_zero_class.zero =?= field.zero
[type_context.is_def_eq_detail] [16]: monoid_with_zero.zero =?= field.zero
[type_context.is_def_eq_detail] [17]: semiring.zero =?= field.zero
[type_context.is_def_eq_detail] [18]: ring.zero =?= field.zero
[type_context.is_def_eq_detail] [19]: division_ring.zero =?= field.zero
[type_context.is_def_eq_detail] [2]: fin ?m_1.succ =?= fin 2
[type_context.is_def_eq_detail] [3]: ?m_1.succ =?= 2
[type_context.is_def_eq] vec_cons ?m_3 ?m_4 = λ (_x : fin ?m_1.succ), 0 =?= ![1, 0] = 0 ... success (approximate mode)
With rw
the "synthesized instances on left" message never appears and the failure is
...
[type_context.is_def_eq_detail] [15]: 0 =?= field.zero
[type_context.is_def_eq_detail] [16]: has_zero.zero =?= field.zero
[type_context.is_def_eq_detail] on failure: has_zero.zero =?= field.zero
[type_context.is_def_eq_detail] on failure: 0 =?= field.zero
[type_context.is_def_eq_detail] on failure: {zero := λ (_x : fin 1.succ), 0} =?= {zero := add_monoid.zero (add_group.to_add_monoid (fin 2 → L))}
[type_context.is_def_eq_detail] [3]: λ (_x : fin 1.succ), 0 =?= add_monoid.zero
[type_context.is_def_eq_detail] [4]: λ (_x : fin 1.succ), 0 =?= add_group.zero
[type_context.is_def_eq_detail] [5]: λ (_x : fin 1.succ), 0 =?= add_comm_group.zero
[type_context.is_def_eq_detail] [6]: λ (_x : fin 1.succ), 0 =?= 0
[type_context.is_def_eq_detail] [7]: 0 =?= 0
[type_context.is_def_eq_detail] [8]: (λ (ᾰ : fin 1.succ), L) _x =?= (λ (i : fin 2), (λ (ᾰ : fin 2), L) i) _x
[type_context.is_def_eq_detail] after whnf_core: L =?= L
[type_context.is_def_eq_detail] [8]: (λ (i : fin 1.succ), ?m_1) _x =?= (λ (i : fin 2), add_monoid.to_has_zero ((λ (ᾰ : fin 2), L) i)) _x
[type_context.is_def_eq_detail] after whnf_core: ?m_1 =?= add_monoid.to_has_zero ((λ (ᾰ : fin 2), L) _x)
[type_context.is_def_eq_detail] process_assignment ?m_1 := add_monoid.to_has_zero ((λ (ᾰ : fin 2), L) _x)
[type_context.is_def_eq_detail] failed to assign ?m_1 to
add_monoid.to_has_zero ((λ (ᾰ : fin 2), L) _x)
value contains local declaration _x which is not in the scope of the metavariable
[type_context.is_def_eq_detail] [8]: 0 =?= add_monoid.zero
[type_context.is_def_eq_detail] [9]: 0 =?= add_group.zero
[type_context.is_def_eq_detail] [10]: 0 =?= add_comm_group.zero
[type_context.is_def_eq_detail] [11]: 0 =?= ring.zero
[type_context.is_def_eq_detail] [12]: 0 =?= division_ring.zero
[type_context.is_def_eq_detail] [13]: 0 =?= field.zero
[type_context.is_def_eq_detail] [14]: has_zero.zero =?= field.zero
[type_context.is_def_eq_detail] on failure: has_zero.zero =?= field.zero
[type_context.is_def_eq_detail] on failure: 0 =?= field.zero
[type_context.is_def_eq_detail] on failure: vec_cons ?m_3 ?m_4 = 0 =?= ![1, 0] = 0
[type_context.is_def_eq] vec_cons ?m_3 ?m_4 = 0 =?= ![1, 0] = 0 ... failed (approximate mode)
Kevin Buzzard (Nov 27 2020 at 19:38):
but now I'm at the limit of my understanding.
Last updated: Dec 20 2023 at 11:08 UTC