Zulip Chat Archive
Stream: mathlib4
Topic: exact_mod_cast and rationals
Eric Wieser (Nov 18 2024 at 17:26):
Is there a tactic that can solve these "trivial" goals, besides doing the sequence of manual rewrites?
import Mathlib
example {x : ℚ} (h : (x : ℝ) = 1 + 2) : x = 1 + 2 := by
exact_mod_cast h -- ok
example {x : ℚ} (h : (x : ℝ) = 1 / 2) : x = 1 / 2 := by
exact_mod_cast h -- fails
example {x : ℚ} (h : (x : ℝ) = 1 + 2 / 3 + 0.5) : x = 1 + 2 / 3 + 0.5 := by
exact_mod_cast h -- fails
Heather Macbeth (Nov 18 2024 at 18:10):
In both cases you can do rify; exact h
. But it seems like it would be better to teach norm_cast
to handle fractions and decimals.
Floris van Doorn (Nov 19 2024 at 18:32):
I thought norm_cast
could already do this, because it can deal with fractions:
import Mathlib.Tactic
example {p q x : ℚ} (h : (x : ℝ) = p / q) : x = p / q := by
norm_cast at h
So it fails only on fractions with a number as both numerator and denominator.
And indeed:
src#Lean.Elab.Tactic.NormCast.derive
has a preprocessing step for dealing with natural number numerals, but not for rationals/decimals.
(and negative numbers are just negation applied to a natural number, so need no special preprocessing).
Eric Wieser (Nov 19 2024 at 23:48):
I think it is pretty tricky to teach it about rational numbers, since norm_cast
is in core where Rat
doesn't exist yet
Heather Macbeth (Nov 19 2024 at 23:56):
Maybe that's a reason to move norm_cast back to Batteries.
Eric Wieser (Nov 20 2024 at 00:00):
I was hoping that something like this might work, but it seems to just send norm_cast into an infinite loop:
import Mathlib
/-- Try to pull casts of numeric literals outside division -/
@[norm_cast move]
theorem Rat.cast_natCast_div_natCast [DivisionRing K] [CharZero K] (n d : ℕ) : (n / d : K) = (n / d : ℚ) := by simp
example {x : ℚ} (h : (x : ℝ) = 2 / 3) : x = 1 + 2 / 3 := by
norm_cast at h
Eric Wieser (Nov 20 2024 at 00:03):
Oh, I can make this work!
Eric Wieser (Nov 20 2024 at 00:06):
@[norm_cast]
theorem Rat.cast_ofNat_div_ofNat [DivisionRing K] [CharZero K] (n d : ℕ) [n.AtLeastTwo] [d.AtLeastTwo]:
(no_index (OfNat.ofNat n) / no_index (OfNat.ofNat d) : ℚ) =
((no_index (OfNat.ofNat n) : ℕ) / (no_index (OfNat.ofNat d) : ℕ) : K)
:= by simp
fixes the example with rationals
Heather Macbeth (Nov 20 2024 at 00:08):
Can you get OfScientific working too?
Eric Wieser (Nov 20 2024 at 00:08):
No, because the mechanism to make OfNat
work is to insert a Nat.cast
Eric Wieser (Nov 20 2024 at 00:09):
So to make OfScientific
work, we need to insert a Rat.cast
(or NNRat.cast
if we have a taste for worms)
Eric Wieser (Nov 20 2024 at 00:09):
Which of course core can't do
Eric Wieser (Nov 20 2024 at 00:11):
What core could do is handle Rat.cast_ofScientific
specially, when it sees it has been tagged norm_cast
Eric Wieser (Nov 20 2024 at 00:24):
Allowing simprocs to be registered with norm_cast would probably work too
Last updated: May 02 2025 at 03:31 UTC