Zulip Chat Archive

Stream: general

Topic: rw: equality is not an equality


Kevin Buzzard (May 06 2020 at 20:25):

I've never seen anything like this before. rw h2 on line 26 fails because it claims h2 is not an equality. But it is, and rw h2.symm.symm works fine. What's going on?

def fibZ :   
| 0 := 0
| 1 := 1
| (n + 2) := fibZ n + fibZ (n + 1)

@[simp] lemma fibZ_0 : fibZ 0 = 0 := rfl
@[simp] lemma fibZ_1 : fibZ 1 = 1 := rfl
@[simp] lemma fibZ_succ_succ (n : ) : fibZ (n + 2) = fibZ n + fibZ (n + 1) := rfl

lemma induction2 (P :   Prop) (h0 : P 0) (h1 : P 1)
  (hind :  d : , P d  P(d+1)  P(d+2)) :  n, P n := sorry

lemma fibZ_m_n (m n : ) : fibZ(m+n+1)=fibZ(m+1)*fibZ(n+1)+fibZ(m)*fibZ(n) :=
begin
  apply induction2 _ _ _ _ n,
  { simp},
  { show fibZ (m + 2) = fibZ (m + 1) * 1 + fibZ m * 1 ,
    rw fibZ_succ_succ,
    simp [add_comm]},
  { -- inductive step
    intros d h1 h2,
    show fibZ (m + (d + 1) + 2) = fibZ (m + 1) * fibZ ((d + 1) + 2) + fibZ m * fibZ (d + 2),
    rw fibZ_succ_succ d,
    rw fibZ_succ_succ (d+1),
    rw fibZ_succ_succ (m+(d+1)),
  --  rw h2, -- "lemma is not an equality or iff"    <---- is this a bug?
    rw h2.symm.symm, -- works fine
    rw [add_assoc m],
    rw h1.symm.symm,
    simp [mul_add, mul_comm, add_comm, add_assoc, mul_assoc],
    ac_refl,
  }
end

Mario Carneiro (May 06 2020 at 20:26):

it's probably an instantiated metavariable

Kevin Buzzard (May 06 2020 at 20:26):

you mean a variable?

Mario Carneiro (May 06 2020 at 20:26):

no

Kevin Buzzard (May 06 2020 at 20:26):

oh

Mario Carneiro (May 06 2020 at 20:26):

It has type h2 : ?m where ?m := a = b or somesuch

Kevin Buzzard (May 06 2020 at 20:27):

how do I test for this?

Mario Carneiro (May 06 2020 at 20:27):

this is pretty printed as h2 : a = b but rw is fussy about it in this particular case

Kevin Buzzard (May 06 2020 at 20:27):

but pp.all doesn't show it me, right?

Kevin Buzzard (May 06 2020 at 20:28):

simp at h2 before the rewrite fixes it

Kevin Buzzard (May 06 2020 at 20:28):

So did I write bad code to get this situation?

Kevin Buzzard (May 06 2020 at 20:29):

my code looks really innocuous and fine

Kevin Buzzard (May 06 2020 at 20:31):

if I change apply induction2 _ _ _ _ n to refine induction2 _ _ _ _ n the problem goes away

Chris Hughes (May 06 2020 at 20:32):

What is an instantiated metavariable?

Mario Carneiro (May 06 2020 at 20:33):

lemma fibZ_m_n (m n : ) : fibZ(m+n+1)=fibZ(m+1)*fibZ(n+1)+fibZ(m)*fibZ(n) :=
begin
  apply induction2 _ _ _ _ n,
  { simp},
  { show fibZ (m + 2) = fibZ (m + 1) * 1 + fibZ m * 1 ,
    rw fibZ_succ_succ,
    simp [add_comm]},
  { -- inductive step
    intros d h1 h2,
    show fibZ (m + (d + 1) + 2) = fibZ (m + 1) * fibZ ((d + 1) + 2) + fibZ m * fibZ (d + 2),
    rw fibZ_succ_succ d,
    rw fibZ_succ_succ (d+1),
    rw fibZ_succ_succ (m+(d+1)),
    (do t  tactic.to_expr```(h2) >>= tactic.infer_type,
      -- t ← tactic.instantiate_mvars t, -- uncomment this line
      tactic.trace (expr.to_raw_fmt t)
      -- (app (mvar _mlocal._fresh.378.4796 _mlocal._fresh.378.4796 (const 2 []))
      --   (app (app (app (app (const has_add.add [0]) (const nat [])) (const nat.has_add []))
      --   (local_const 0._fresh.378.6836 d (const 1 []))) (app (app (const has_one.one [0])
      --   (const nat [])) (const nat.has_one []))))
    ),
    -- rw h2, -- "lemma is not an equality or iff"    <---- is this a bug?
    rw h2.symm.symm, -- works fine
    rw [add_assoc m],
    rw h1.symm.symm,
    simp [mul_add, mul_comm, add_comm, add_assoc, mul_assoc],
    ac_refl,
  }
end

Mario Carneiro (May 06 2020 at 20:34):

expr.to_raw_fmt is like the super verbose version of pp.all

Mario Carneiro (May 06 2020 at 20:34):

it shows you exactly what constructors of the expr type are being used

Mario Carneiro (May 06 2020 at 20:35):

As you can see, it starts (app (mvar ...

Kenny Lau (May 06 2020 at 20:35):

then where is the information stored that ?m_2 is eq?

Mario Carneiro (May 06 2020 at 20:35):

in the local context, not somewhere easily accessible to lean except through builtins like instantiate_mvars

Kenny Lau (May 06 2020 at 20:36):

can we tell intro to instantiate metavariables?

Mario Carneiro (May 06 2020 at 20:37):

I haven't looked at what is causing the problem in the first place in this case

Mario Carneiro (May 06 2020 at 20:39):

The only metavariable that intro instantiates is the goal. It doesn't have to solve any unification problems

Mario Carneiro (May 06 2020 at 20:42):

It might make things clearer to replace the first line with:

  have := induction2 _ _ _ _ n, apply this,

After the have, the state is

5 goals
m n : ,
this : ?m_1 n
 fibZ (m + n + 1) = fibZ (m + 1) * fibZ (n + 1) + fibZ m * fibZ n

m n : 
   Prop

m n : 
 ?m_1 0

m n : 
 ?m_1 1

m n : 
  (d : ), ?m_1 d  ?m_1 (d + 1)  ?m_1 (d + 2)

The thing that will eventually become the type of h2 is here ?m_1 (d + 1)

Kevin Buzzard (May 06 2020 at 20:43):

The problem is somehow with the apply on the first line.

Kevin Buzzard (May 06 2020 at 20:43):

yeah, that. refine fixes it.

Mario Carneiro (May 06 2020 at 20:43):

Because refine knows the expected type, and apply doesn't, elaboration happens in a different order here

Mario Carneiro (May 06 2020 at 20:44):

apply is doing the above two stage process, while refine never creates ?m_1 (d + 1) because it already knows what ?m_1 is

Kevin Buzzard (May 06 2020 at 20:45):

When I saw the underscores I thought about maybe making induction2_on and applying that instead; I don't know if that would have fixed the problem.

Kevin Buzzard (May 06 2020 at 20:45):

[this code is for pedagogical purposes]

Mario Carneiro (May 06 2020 at 20:46):

Notice that the variable in question is pretty far from apply's strike zone. It's in a subterm of a different goal

Mario Carneiro (May 06 2020 at 20:47):

I'm not sure if this is a factor, but there is a performance penalty for instantiate_mvars because it has to traverse the whole term, while most tactics try to keep track of where all the metavariables are so that they don't have to go hunting

Mario Carneiro (May 06 2020 at 20:49):

But the check in rw is just plain broken. It's pattern matching on the expr and assumes that an mvar is not an eq. This is a very common pattern, but it is not safe against rogue terms with instantiated mvars

Mario Carneiro (May 06 2020 at 20:54):

Here's another example that often comes up for me:

example (n : ) (h : n + n  0) : n  0 :=
begin
  refine mt (λ hz, _) h,
  rw hz -- rewrite tactic failed, lemma is not an equality nor a iff
end

Mario Carneiro (May 06 2020 at 20:55):

The type of hz is an instantiated metavariable here because it is unknown when it is created by the lambda and is solved by the h to its right

Patrick Massot (May 06 2020 at 20:55):

I think you complain periodically about that one. Couldn't you change that in Lean 3.13?

Patrick Massot (May 06 2020 at 20:55):

(I lost track of what it the next version)

Mario Carneiro (May 06 2020 at 21:00):

instantiated mvars or the rw check?

Patrick Massot (May 06 2020 at 21:00):

The rw check

Mario Carneiro (May 06 2020 at 21:00):

I know nothing about the code in question but it shouldn't be hard

Patrick Massot (May 06 2020 at 21:01):

I think you already found the offending line at some point

Mario Carneiro (May 06 2020 at 21:08):

I'm building lean now, if I can remember how to do that

Bhavik Mehta (May 06 2020 at 21:24):

I've seen this a couple of times but only very recently

Mario Carneiro (May 06 2020 at 21:25):

lean#213

Reid Barton (May 06 2020 at 22:34):

BTW, this "instantiation" is more formally known as zonking


Last updated: Dec 20 2023 at 11:08 UTC