Skip to content
New issue

Have a question about this project? Sign up for a free GitHub account to open an issue and contact its maintainers and the community.

By clicking “Sign up for GitHub”, you agree to our terms of service and privacy statement. We’ll occasionally send you account related emails.

Already on GitHub? Sign in to your account

[Merged by Bors] - feat: recognize scientific notation in norm_num #1707

Closed
wants to merge 32 commits into from
Closed
Show file tree
Hide file tree
Changes from 17 commits
Commits
Show all changes
32 commits
Select commit Hold shift + click to select a range
585c09e
feat: `Int.ofNat` extension
thorimur Feb 2, 2023
100845b
test: `Int.ofNat` extension
thorimur Feb 2, 2023
b14d8ff
feat: `RatCast.ratCast` extension
thorimur Feb 2, 2023
2daa784
feat: `mkRat` extension
thorimur Feb 2, 2023
373420b
test: `mkRat` extension
thorimur Feb 2, 2023
3144f22
feat: `OfScientific` instance for `DivisionRing`s
thorimur Feb 2, 2023
f8c5538
feat: `LawfulOfScientific` class
thorimur Feb 2, 2023
e47a7d3
feat: `LawfulOfScientific` instances
thorimur Feb 2, 2023
f382d6b
fix: `mul` `invOf` simp lemmas use unification
thorimur Feb 2, 2023
be618af
feat: `ofScientific` extension
thorimur Feb 2, 2023
be5cb2b
test: `ofScientific` extension
thorimur Feb 2, 2023
e38ffe7
formatting: sections in `NormNum.Basic`
thorimur Feb 2, 2023
83e80b1
formatting: misc. cleanup in `NormNum.Basic`
thorimur Feb 2, 2023
b703669
Merge remote-tracking branch 'origin/master' into norm_num-scientific
thorimur Feb 3, 2023
dfc4bc9
formatting: fix section headings
thorimur Feb 3, 2023
417e80a
chore: misc. cleanup
thorimur Feb 7, 2023
68bf4b0
Merge remote-tracking branch 'origin/master' into norm_num-scientific
thorimur Feb 7, 2023
49e07e6
Merge remote-tracking branch 'origin/master' into norm_num-scientific
thorimur Mar 8, 2023
e33d74b
docs: explain `Invertible.lean` changes
thorimur Mar 8, 2023
21f511f
Merge remote-tracking branch 'origin/master' into norm_num-scientific
thorimur Mar 17, 2023
4e88c01
refactor: remove `LawfulOfScientific`
thorimur Mar 17, 2023
00e977c
fix: ofScientific lemmas
thorimur Mar 17, 2023
60083df
fix: `evalOfScientific`
thorimur Mar 17, 2023
52b3429
chore: remove leftover to_additive from old merge
thorimur Mar 17, 2023
8b32ac6
chore: become a test and `NormNum.Basic` author
thorimur Mar 17, 2023
6dbefe1
feat: (`Nat`/`Int`/`Rat`)`.cast` adjustments
thorimur Mar 17, 2023
ee3c11c
docs tweak: `Invertible.lean` wording
thorimur Mar 18, 2023
0750407
style: tweak wording, small formatting changes
thorimur Mar 18, 2023
6f857dd
Merge remote-tracking branch 'origin/master' into norm_num-scientific
thorimur Mar 27, 2023
86557b7
fix: lemmas
thorimur Mar 27, 2023
ebb896a
fix: use derived nat lits for `false` case
thorimur Mar 27, 2023
9fa0484
fix: tidy `mkRat`, `Int.ofNat` evaluators
thorimur Mar 28, 2023
File filter

Filter by extension

Filter by extension

Conversations
Failed to load comments.
Loading
Jump to
Jump to file
Failed to load files.
Loading
Diff view
Diff view
17 changes: 17 additions & 0 deletions Mathlib/Algebra/Field/Defs.lean
Original file line number Diff line number Diff line change
Expand Up @@ -174,6 +174,23 @@ end Rat

end DivisionRing

section OfScientific

instance DivisionRing.toOfScientific [DivisionRing K] : OfScientific K where
ofScientific (m : ℕ) (b : Bool) (d : ℕ) := Rat.ofScientific m b d

/-- A class which states that an `OfScientific α` instance is propositionally equal to the cast of
the canonical `OfScientific Rat` instance, assuming we have `RatCast α`. -/
class LawfulOfScientific (α) [OfScientific α] [RatCast α] : Prop where
/-- However `ofScientific` is defined, it's pointwise equal to the cast of `Rat.ofScientific`. -/
ofScientific_eq (m : ℕ) (b : Bool) (d : ℕ) :
OfScientific.ofScientific m b d = (Rat.ofScientific m b d : α)

instance [DivisionRing α] : LawfulOfScientific α where
ofScientific_eq _ _ _ := rfl

end OfScientific

section Field

variable [Field K]
Expand Down
18 changes: 18 additions & 0 deletions Mathlib/Algebra/Invertible.lean
Original file line number Diff line number Diff line change
Expand Up @@ -81,31 +81,49 @@ prefix:max
Invertible.invOf

@[simp]
theorem invOf_mul_self' [Mul α] [One α] (a : α) {_ : Invertible a} : ⅟ a * a = 1 :=
semorrison marked this conversation as resolved.
Show resolved Hide resolved
Invertible.invOf_mul_self

theorem invOf_mul_self [Mul α] [One α] (a : α) [Invertible a] : ⅟ a * a = 1 :=
Invertible.invOf_mul_self
#align inv_of_mul_self invOf_mul_self

@[simp]
theorem mul_invOf_self' [Mul α] [One α] (a : α) {_ : Invertible a} : a * ⅟ a = 1 :=
Invertible.mul_invOf_self

theorem mul_invOf_self [Mul α] [One α] (a : α) [Invertible a] : a * ⅟ a = 1 :=
Invertible.mul_invOf_self
#align mul_inv_of_self mul_invOf_self

@[simp]
theorem invOf_mul_self_assoc' [Monoid α] (a b : α) {_ : Invertible a} : ⅟ a * (a * b) = b := by
rw [← mul_assoc, invOf_mul_self, one_mul]

theorem invOf_mul_self_assoc [Monoid α] (a b : α) [Invertible a] : ⅟ a * (a * b) = b := by
rw [← mul_assoc, invOf_mul_self, one_mul]
#align inv_of_mul_self_assoc invOf_mul_self_assoc

@[simp]
theorem mul_invOf_self_assoc' [Monoid α] (a b : α) {_ : Invertible a} : a * (⅟ a * b) = b := by
rw [← mul_assoc, mul_invOf_self, one_mul]

theorem mul_invOf_self_assoc [Monoid α] (a b : α) [Invertible a] : a * (⅟ a * b) = b := by
rw [← mul_assoc, mul_invOf_self, one_mul]
#align mul_inv_of_self_assoc mul_invOf_self_assoc

@[simp]
theorem mul_invOf_mul_self_cancel' [Monoid α] (a b : α) {_ : Invertible b} : a * ⅟ b * b = a := by
simp [mul_assoc]

theorem mul_invOf_mul_self_cancel [Monoid α] (a b : α) [Invertible b] : a * ⅟ b * b = a := by
simp [mul_assoc]
#align mul_inv_of_mul_self_cancel mul_invOf_mul_self_cancel

@[simp]
theorem mul_mul_invOf_self_cancel' [Monoid α] (a b : α) {_ : Invertible b} : a * b * ⅟ b = a := by
simp [mul_assoc]

theorem mul_mul_invOf_self_cancel [Monoid α] (a b : α) [Invertible b] : a * b * ⅟ b = a := by
simp [mul_assoc]
#align mul_mul_inv_of_self_cancel mul_mul_invOf_self_cancel
Expand Down
7 changes: 7 additions & 0 deletions Mathlib/Data/Rat/Cast.lean
Original file line number Diff line number Diff line change
Expand Up @@ -536,3 +536,10 @@ instance isScalarTower_right : IsScalarTower ℚ K K :=
end Rat

end SMul

section OfScientific

instance : LawfulOfScientific Rat where
ofScientific_eq _ _ _ := rfl

end OfScientific
20 changes: 20 additions & 0 deletions Mathlib/Data/Rat/Defs.lean
Original file line number Diff line number Diff line change
Expand Up @@ -251,6 +251,15 @@ theorem divInt_neg_one_one : -1 /. 1 = -1 :=
rfl
#align rat.mk_neg_one_one Rat.divInt_neg_one_one

theorem divInt_one (n : ℤ) : n /. 1 = n :=
show divInt _ _ = _ by
rw [divInt]
simp [mkRat, normalize]
rfl

theorem mkRat_one {n : ℤ} : mkRat n 1 = n := by
simp [Rat.mkRat_eq, Rat.divInt_one]

#align rat.mul_one Rat.mul_one
#align rat.one_mul Rat.one_mul
#align rat.mul_comm Rat.mul_comm
Expand Down Expand Up @@ -541,6 +550,17 @@ theorem coe_int_inj (m n : ℤ) : (m : ℚ) = n ↔ m = n :=

end Casts

theorem mkRat_eq_div {n : ℤ} {d : ℕ} : mkRat n d = n / d := by
simp [mkRat]
by_cases d = 0
· simp [h]
· simp [h, HDiv.hDiv, Rat.div, Div.div]
unfold Rat.inv
have h₁ : 0 < d := Nat.pos_iff_ne_zero.2 h
have h₂ : ¬ (d : ℤ) < 0 := by simp
simp [h, h₁, h₂, ←Rat.normalize_eq_mk', Rat.normalize_eq_mkRat, ← mkRat_one,
Rat.mkRat_mul_mkRat]

end Rat

-- Porting note: `assert_not_exists` is not implemented yet.
Expand Down
149 changes: 135 additions & 14 deletions Mathlib/Tactic/NormNum/Basic.lean
Original file line number Diff line number Diff line change
Expand Up @@ -15,12 +15,14 @@ This file adds `norm_num` plugins for `+`, `*` and `^` along with other basic op
-/

namespace Mathlib
open Lean hiding Rat
open Lean hiding Rat mkRat
open Meta

namespace Meta.NormNum
open Qq

/-! # Constructors and constants -/

theorem isNat_zero (α) [AddMonoidWithOne α] : IsNat (Zero.zero : α) (nat_lit 0) :=
⟨Nat.cast_zero.symm⟩

Expand Down Expand Up @@ -52,6 +54,21 @@ theorem isNat_ofNat (α : Type u_1) [AddMonoidWithOne α] {a : α} {n : ℕ}
guard <|← isDefEq a e
return .isNat sα n (q(isNat_ofNat $α $pa) : Expr)

theorem isNat_intOfNat : {n n' : ℕ} → IsNat n n' → IsNat (Int.ofNat n) n'
| _, _, ⟨rfl⟩ => ⟨rfl⟩

/-- The `norm_num` extension which identifies the constructor application `Int.ofNat n` such that
`norm_num` successfully recognizes `n`, returning `n`. -/
@[norm_num Int.ofNat _] def evalIntOfNat : NormNumExt where eval {u α} e := do
let .app _ (n : Q(ℕ)) ← whnfR e | failure
guard <| α.isConstOf ``Int
let sℕ : Q(AddMonoidWithOne ℕ) := q(AddCommMonoidWithOne.toAddMonoidWithOne)
let sℤ : Q(AddMonoidWithOne ℤ) := q(AddGroupWithOne.toAddMonoidWithOne)
let ⟨n', p⟩ ← deriveNat n sℕ
return (.isNat sℤ n' q(isNat_intOfNat $p) : Result q(Int.ofNat $n))

/-! # Casts -/

theorem isNat_cast {R} [AddMonoidWithOne R] (n m : ℕ) :
IsNat n m → IsNat (n : R) m := by rintro ⟨⟨⟩⟩; exact ⟨rfl⟩

Expand Down Expand Up @@ -85,6 +102,43 @@ theorem isInt_cast {R} [Ring R] (n m : ℤ) :
return (.isNegNat rα na q(isInt_cast $a (.negOfNat $na) $pa) : Result q(Int.cast $a : $α))
| _ => failure

theorem isNat_ratCast [DivisionRing R] : {q : ℚ} → {n : ℕ} →
IsNat q n → IsNat (q : R) n
| _, _, ⟨rfl⟩ => ⟨by simp⟩

theorem isInt_ratCast [DivisionRing R] : {q : ℚ} → {n : ℤ} →
IsInt q n → IsInt (q : R) n
| _, _, ⟨rfl⟩ => ⟨by simp⟩

theorem isRat_ratCast [DivisionRing R] [CharZero R] : {q : ℚ} → {n : ℤ} → {d : ℕ} →
IsRat q n d → IsRat (q : R) n d
| _, _, _, ⟨⟨qi,_,_⟩, rfl⟩ => ⟨⟨qi, by norm_cast, by norm_cast⟩, by simp only []; norm_cast⟩

/-- The `norm_num` extension which identifies an expression `RatCast.ratCast q` where `norm_num`
recognizes `q`, returning the cast of `q`. -/
@[norm_num RatCast.ratCast _] def evalRatCast : NormNumExt where eval {u α} e := do
let dα ← inferDivisionRing α
match e with
| ~q(RatCast.ratCast $a) =>
let r ← derive (α := q(ℚ)) a
match r with
| .isNat _ na pa =>
let sα : Q(AddMonoidWithOne $α) := q(instAddMonoidWithOne')
let pa : Q(@IsNat _ instAddMonoidWithOne' $a $na) := pa
return (.isNat sα na q(@isNat_ratCast $α _ $a $na $pa) : Result q(RatCast.ratCast $a : $α))
| .isNegNat _ na pa =>
let rα : Q(Ring $α) := q(instRing)
let pa : Q(@IsInt _ instRing $a (.negOfNat $na)) := pa
return (.isNegNat rα na q(@isInt_ratCast $α _ $a (.negOfNat $na) $pa) :
Result q(RatCast.ratCast $a : $α))
| .isRat _ qa na da pa =>
let i ← inferCharZeroOfDivisionRing dα
let pa : Q(@IsRat _ instRingRat $a $na $da) := pa
return (.isRat dα qa na da q(isRat_ratCast $pa) : Result q(RatCast.ratCast $a : $α))
| _ => failure

/-! # Arithmetic -/

theorem isNat_add {α} [AddMonoidWithOne α] : {a b : α} → {a' b' c : ℕ} →
IsNat a a' → IsNat b b' → Nat.add a' b' = c → IsNat (a + b) c
| _, _, _, _, _, ⟨rfl⟩, ⟨rfl⟩, rfl => ⟨(Nat.cast_add _ _).symm⟩
Expand Down Expand Up @@ -424,33 +478,33 @@ such that `norm_num` successfully recognises `a`. -/
let ⟨qa, na, da, pa⟩ ← ra.toRat'
let qb := qa⁻¹
if qa > 0 then
if let .some _i := _i then
if let some _i := _i then
have lit : Q(ℕ) := na.appArg!
have lit2 : Q(ℕ) := mkRawNatLit (lit.natLit! - 1)
let pa : Q(IsRat «$a» (Int.ofNat (Nat.succ $lit2)) $da) := pa
let pa : Q(IsRat $a (Int.ofNat (Nat.succ $lit2)) $da) := pa
return (.isRat' dα qb q(.ofNat $da) lit
(q(isRat_inv_pos (α := $α) $pa) : Expr) : Result q($a⁻¹))
else
guard (qa = 1)
let .isNat inst _z
let .isNat inst n
(pa : Q(@IsNat _ AddGroupWithOne.toAddMonoidWithOne $a (nat_lit 1))) := ra | failure
return (.isNat inst _z (q(isRat_inv_one $pa) : Expr) : Result q($a⁻¹))
return (.isNat inst n (q(isRat_inv_one $pa) : Expr) : Result q($a⁻¹))
else if qa < 0 then
if let .some _i := _i then
if let some _i := _i then
have lit : Q(ℕ) := na.appArg!
have lit2 : Q(ℕ) := mkRawNatLit (lit.natLit! - 1)
let pa : Q(IsRat «$a» (Int.negOfNat (Nat.succ $lit2)) $da) := pa
let pa : Q(IsRat $a (Int.negOfNat (Nat.succ $lit2)) $da) := pa
return (.isRat' dα qb q(.negOfNat $da) lit
(q(isRat_inv_neg (α := $α) $pa) : Expr) : Result q($a⁻¹))
else
guard (qa = -1)
let .isNegNat inst _z
let .isNegNat inst n
(pa : Q(@IsInt _ DivisionRing.toRing $a (.negOfNat 1))) := ra | failure
return (.isNegNat inst _z (q(isRat_inv_neg_one $pa) : Expr) : Result q($a⁻¹))
return (.isNegNat inst n (q(isRat_inv_neg_one $pa) : Expr) : Result q($a⁻¹))
else
let .isNat inst _z (pa : Q(@IsNat _ AddGroupWithOne.toAddMonoidWithOne $a (nat_lit 0))) := ra
let .isNat inst n (pa : Q(@IsNat _ AddGroupWithOne.toAddMonoidWithOne $a (nat_lit 0))) := ra
| failure
return (.isNat inst _z (q(isRat_inv_zero $pa) : Expr) : Result q($a⁻¹))
return (.isNat inst n (q(isRat_inv_zero $pa) : Expr) : Result q($a⁻¹))
core

theorem isRat_div [DivisionRing α] : {a b : α} → {cn : ℤ} → {cd : ℕ} → IsRat (a * b⁻¹) cn cd →
Expand All @@ -468,6 +522,73 @@ such that `norm_num` successfully recognises both `a` and `b`. -/
let pa : Q(IsRat ($a * $b⁻¹) $na $da) := pa
return (.isRat' dα qa na da q(isRat_div $pa) : Result q($a / $b))

/-! # Constructor-like operations -/

theorem isRat_mkRat : {a na n : ℤ} → {b nb d : ℕ} → IsInt a na → IsNat b nb →
IsRat (na / nb : ℚ) n d → IsRat (mkRat a b) n d
| _, _, _, _, _, _, ⟨rfl⟩, ⟨rfl⟩, ⟨_, h⟩ => by rw [Rat.mkRat_eq_div]; exact ⟨_, h⟩

/-- The `norm_num` extension which identifies expressions of the form `mkRat a b`,
such that `norm_num` successfully recognises both `a` and `b`, and returns `a / b`. -/
@[norm_num mkRat _ _] def evalMkRat : NormNumExt where eval {u α} e := do
let .app (.app _ (a : Q(ℤ))) (b : Q(ℕ)) ← whnfR e | failure
guard <| α.isConstOf ``Rat
let ra ← derive a
let rℤ : Q(Ring ℤ) := q(Int.instRingInt)
let some ⟨_, na, pa⟩ := ra.toInt | failure
let sℕ : Q(AddMonoidWithOne ℕ) := q(AddCommMonoidWithOne.toAddMonoidWithOne)
let ⟨nb, pb⟩ ← deriveNat b sℕ
let rab ← derive (q($na / $nb) : Q(Rat))
let dℚ : Q(DivisionRing ℚ) := q(Rat.divisionRing)
let ⟨q, n, d, p⟩ ← rab.toRat' dℚ
let p : Q(IsRat ($na / $nb : ℚ) $n $d) := p
return (.isRat' (inst := dℚ) q n d q(isRat_mkRat $pa $pb $p) : Result q(mkRat $a $b))

theorem isRat_ofScientific_of_true [DivisionRing α] [OfScientific α] [LawfulOfScientific α] :
{m e : ℕ} → {n : ℤ} → {d : ℕ} → IsRat (mkRat m (10 ^ e) : α) n d →
IsRat (OfScientific.ofScientific (α := α) m true e) n d
| _, _, _, _, ⟨_, eq⟩ => ⟨_, by
simp only [LawfulOfScientific.ofScientific_eq, if_true, Rat.ofScientific,
Rat.normalize_eq_mkRat]
exact eq⟩

theorem isNat_ofScientific_of_false [dα : DivisionRing α] [OfScientific α] [LawfulOfScientific α] :
{m e nm ne n : ℕ} → IsNat m nm → IsNat e ne → n = Nat.mul nm ((10 : ℕ) ^ ne) →
IsNat (OfScientific.ofScientific (α := α) m false e) n
| _, _, _, _, _, ⟨rfl⟩, ⟨rfl⟩, h =>
⟨by simp [LawfulOfScientific.ofScientific_eq, Rat.ofScientific, h]; norm_cast⟩

/-- The `norm_num` extension which identifies expressions in scientific notation, normalizing them
to rat casts if the scientific notation is inherited from the one for rationals. -/
@[norm_num OfScientific.ofScientific _ _ _] def evalOfScientific :
NormNumExt where eval {u α} e := do
let .app (.app (.app f (m : Q(ℕ))) (b : Q(Bool))) (exp : Q(ℕ)) ← whnfR e | failure
let σα ← inferOfScientific α
guard <|← withNewMCtxDepth <| isDefEq f q(OfScientific.ofScientific (α := $α))
let dα ← inferDivisionRing α
let lσα ← inferLawfulOfScientific dα σα
match b with
| ~q(true) =>
let rme ← derive (q(mkRat $m (10 ^ $exp)) : Q($α))
let some ⟨q, n, d, p⟩ := rme.toRat' | failure
let p : Q(IsRat (mkRat $m (10 ^ $exp) : $α) $n $d) := p
return (.isRat' dα q n d q(isRat_ofScientific_of_true $p) :
Result q(@OfScientific.ofScientific $α $σα $m true $exp))
| ~q(false) =>
let ⟨nm, pm⟩ ← deriveNat m q(AddCommMonoidWithOne.toAddMonoidWithOne)
let ⟨ne, pe⟩ ← deriveNat exp q(AddCommMonoidWithOne.toAddMonoidWithOne)
have pm : Q(IsNat $m $nm) := pm
have pe : Q(IsNat $exp $ne) := pe
let m' := m.natLit!
let exp' := exp.natLit!
let n' := Nat.mul m' (Nat.pow (10 : ℕ) exp')
have n : Q(ℕ) := mkRawNatLit n'
have r : Q($n = Nat.mul $nm ((10 : ℕ) ^ $ne)) := (q(Eq.refl $n) : Expr)
return ((.isNat _ n
(q(isNat_ofScientific_of_false (α := $α) (n := $n) $pm $pe $r) :
Q(IsNat (OfScientific.ofScientific (α := $α) $m false $exp) $n))) :
Result q(@OfScientific.ofScientific $α $σα $m false $exp))

/-! # Logic -/

/-- The `norm_num` extension which identifies `True`. -/
Expand Down Expand Up @@ -607,7 +728,7 @@ such that `norm_num` successfully recognises both `a` and `b`. -/
if za = zb then
let pb : Q(IsInt $b $na) := pb
return (.isTrue q(isInt_eq_true $pa $pb) : Result q($a = $b))
else if let .some _i ← inferCharZeroOfRing? rα then
else if let some _i ← inferCharZeroOfRing? rα then
let r : Q(decide ($na = $nb) = false) := (q(Eq.refl false) : Expr)
return (.isFalse q(isInt_eq_false $pa $pb $r) : Result q($a = $b))
else
Expand All @@ -617,7 +738,7 @@ such that `norm_num` successfully recognises both `a` and `b`. -/
if qa = qb then
let pb : Q(IsRat $b $na $da) := pb
return (.isTrue q(isRat_eq_true $pa $pb) : Result q($a = $b))
else if let .some _i ← inferCharZeroOfDivisionRing? dα then
else if let some _i ← inferCharZeroOfDivisionRing? dα then
let r : Q(decide (Int.mul $na (.ofNat $db) = Int.mul $nb (.ofNat $da)) = false) :=
(q(Eq.refl false) : Expr)
return (.isFalse q(isRat_eq_false $pa $pb $r) : Result q($a = $b))
Expand All @@ -643,7 +764,7 @@ such that `norm_num` successfully recognises both `a` and `b`. -/
if na.natLit!.beq nb.natLit! then
let r : Q(Nat.beq $na $nb = true) := (q(Eq.refl true) : Expr)
return (.isTrue q(isNat_eq_true $pa $pb $r) : Result q($a = $b))
else if let .some _i ← inferCharZeroOfAddMonoidWithOne? mα then
else if let some _i ← inferCharZeroOfAddMonoidWithOne? mα then
let r : Q(Nat.beq $na $nb = false) := (q(Eq.refl false) : Expr)
return (.isFalse q(isNat_eq_false $pa $pb $r) : Result q($a = $b))
else
Expand Down
24 changes: 24 additions & 0 deletions Mathlib/Tactic/NormNum/Core.lean
Original file line number Diff line number Diff line change
Expand Up @@ -214,6 +214,13 @@ and `q` is the value of `n / d`. -/
/-- A shortcut (non)instance for `AddMonoidWithOne α` from `Ring α` to shrink generated proofs. -/
def instAddMonoidWithOne [Ring α] : AddMonoidWithOne α := inferInstance

/-- A shortcut (non)instance for `AddMonoidWithOne α` from `DivisionRing α` to shrink generated
proofs. -/
def instAddMonoidWithOne' [DivisionRing α] : AddMonoidWithOne α := inferInstance

/-- A shortcut (non)instance for `Ring α` from `DivisionRing α` to shrink generated proofs. -/
def instRing [DivisionRing α] : Ring α := inferInstance

/-- The result is `z : ℤ` and `proof : isNat x z`. -/
-- Note the independent arguments `z : Q(ℤ)` and `n : ℤ`.
-- We ensure these are "the same" when calling.
Expand Down Expand Up @@ -306,6 +313,23 @@ exists. -/
def inferCharZeroOfDivisionRing? {α : Q(Type u)}
(_i : Q(DivisionRing $α) := by with_reducible assumption) : MetaM (Option Q(CharZero $α)) :=
return (← trySynthInstanceQ (q(CharZero $α) : Q(Prop))).toOption

/-- Helper function to synthesize a typed `OfScientific α` expression. -/
def inferOfScientific (α : Q(Type u)) : MetaM Q(OfScientific $α) :=
return ← synthInstanceQ (q(OfScientific $α) : Q(Type u)) <|>
throwError "does not support scientific notation"

/-- Helper function to synthesize a typed `LawfulOfScientific α` expression. -/
def inferLawfulOfScientific {α : Q(Type u)}
(_dα : Q(DivisionRing $α) := by with_reducible assumption)
(_sα : Q(OfScientific $α) := by with_reducible assumption) : MetaM Q(LawfulOfScientific $α) :=
return ← synthInstanceQ (q(LawfulOfScientific $α) : Q(Prop)) <|>
throwError "does not support lawful scientific notation"

/-- Helper function to synthesize a typed `RatCast α` expression. -/
def inferRatCast (α : Q(Type u)) : MetaM Q(RatCast $α) :=
return ← synthInstanceQ (q(RatCast $α) : Q(Type u)) <|> throwError "does not support a rat cast"

/--
Extract from a `Result` the integer value (as both a term and an expression),
and the proof that the original expression is equal to this integer.
Expand Down
Loading