Zulip Chat Archive

Stream: mathlib4

Topic: Nat.mod 0 n = 0 no longer true by rfl


Gabriel Ebner (Jan 05 2023 at 23:18):

Lean 4 has special kernel support for computation with Nat.mod (as well as special extern functions for VM computation), so it shouldn't make a big difference if we change the Nat.mod definition.

Gabriel Ebner (Jan 05 2023 at 23:22):

That said, it's a huge coincidence that nat.mod 0 n reduces in Lean 3. If I had picked a different value for the initial fuel, then we wouldn't have that defeq (because 0 < n ∧ n ≤ 0 doesn't reduce).

Eric Wieser (Jan 05 2023 at 23:23):

Given a fair bit of mathlib builds upon that coincidence, it seems a shame to throw away the coincidence without a compelling reason

Notification Bot (Jan 05 2023 at 23:32):

20 messages were moved from this topic to #mathlib4 > Porting Nat.mod_def by Eric Wieser.

Notification Bot (Jan 05 2023 at 23:54):

24 messages were moved here from #mathlib4 > Data.Fin.Basic (mathlib4#1084) by Eric Wieser.

Eric Wieser (Jan 05 2023 at 23:57):

I've created https://github.com/leanprover/lean4/pull/2014 as a draft, mainly to see if CI is happy. What are your thoughts on this, @Gabriel Ebner?

Eric Wieser (Jan 06 2023 at 00:05):

Gabriel Ebner said:

Lean 4 has special kernel support for computation with Nat.mod (as well as special extern functions for VM computation), so it shouldn't make a big difference if we change the Nat.mod definition.

Oh, so I guess that means that the kernel would have to change to match the new implementation?

Mario Carneiro (Jan 06 2023 at 00:05):

the kernel implementation is only for literals

Eric Wieser (Jan 06 2023 at 00:06):

I get a pretty weird error in CI from my change above

Eric Wieser (Jan 06 2023 at 00:06):

A downstream simp call produces an invalid term

Mario Carneiro (Jan 06 2023 at 00:06):

so as long as you haven't actually changed the value of the definition (and since you proved the same defining equation I think it's safe to say this is not the case) the kernel doesn't have to change

Eric Wieser (Jan 06 2023 at 00:07):

This proof:

@[simp] theorem gcd_zero_right (n : Nat) : gcd n 0 = n := by
  cases n <;> simp [gcd_succ]

fails with

application type mismatch
  @Eq.ndrec Nat (succ n) (fun n => gcd n 0 = n)
    (of_eq_true
      (Eq.trans (congrFun (congrArg Eq (congrFun (congrArg gcd (zero_mod (succ n))) (succ n))) (succ n))
        (eq_self (succ n))))
argument has type
  gcd (0 % succ n) (succ n) = succ n
but function has type
  (fun n => gcd n 0 = n) (succ n)   {b : Nat}, succ n = b  (fun n => gcd n 0 = n) b

Eric Wieser (Jan 06 2023 at 00:08):

Which is scary because the term which has a type mismatch is being produced by simp

Eric Wieser (Jan 06 2023 at 00:10):

it works fine as

@[simp] theorem gcd_zero_right (n : Nat) : gcd n 0 = n := by
  cases n with
  | zero => simp [gcd_succ]
  | succ n =>
    rw [gcd_succ]
    exact gcd_zero_left _

Eric Wieser (Jan 06 2023 at 00:10):

But I feel like the failure might be a warning sign

Mario Carneiro (Jan 06 2023 at 00:11):

does simp only [gcd_succ]; sorry work in the second branch?

Eric Wieser (Jan 06 2023 at 00:12):

No, with

application type mismatch
  id (sorryAx (gcd (0 % succ n) (succ n) = succ n))
argument has type
  gcd (0 % succ n) (succ n) = succ n
but function has type
  gcd (succ n) 0 = succ n  gcd (succ n) 0 = succ n

Mario Carneiro (Jan 06 2023 at 00:12):

Can you replicate this outside core?

Eric Wieser (Jan 06 2023 at 00:13):

If I stupidly edited things in .elean/toolchains/..., how do I wipe them and start afresh?

Mario Carneiro (Jan 06 2023 at 00:16):

I think you can use elan toolchain uninstall bla

Eric Wieser (Jan 06 2023 at 00:19):

I think this image is toast, I'll spin up a new one

Eric Wieser (Jan 06 2023 at 00:23):

Yes, it reproduces outside core

Eric Wieser (Jan 06 2023 at 00:29):

(deleted)

Mario Carneiro (Jan 06 2023 at 00:31):

Oh I meant using mod', no prelude

Eric Wieser (Jan 06 2023 at 00:32):

Edited above

Eric Wieser (Jan 06 2023 at 00:35):

Shall I make a lean4 bug report?

Mario Carneiro (Jan 06 2023 at 00:36):

great, now I can use show_term on the simp call:

import Std.Tactic.Basic
...
@[simp] theorem gcd'_zero_right (n : Nat) : gcd' n 0 = n := by
  cases n with
  | zero => simp [gcd'_succ]
  | succ n => show_term simp only [gcd'_succ]; sorry
-- @id (gcd' (succ n) 0 = succ n) (sorryAx (gcd' (Nat.mod' 0 (succ n)) (succ n) = succ n))

Mario Carneiro (Jan 06 2023 at 00:36):

it seems that something was marked as a dsimp lemma that isn't rfl

Eric Wieser (Jan 06 2023 at 00:38):

Changing gcd'_succ to be proved by id rfl makes the error go away

Mario Carneiro (Jan 06 2023 at 00:45):

this could be one of those rare instances of non-transitivity of defeq

Mario Carneiro (Jan 06 2023 at 00:45):

It is surprising that gcd'_succ is provable by rfl in the first place, so using id rfl seems reasonable

Eric Wieser (Jan 08 2023 at 12:14):

Filed as leanprover/lean4#2021


Last updated: Dec 20 2023 at 11:08 UTC