@@ -223,20 +223,19 @@ def _root_.Mathlib.Meta.monadLiftOptionMetaM : MonadLift Option MetaM where
223223 | some e => pure e
224224
225225attribute [local instance ] monadLiftOptionMetaM in
226- /-- Main part of `evalAdd`. -/
227- def evalAdd.core {u : Level} {α : Q(Type u)} (e : Q(«$α »)) (f : Q(«$α » → «$α » → «$α »))
228- (a b : Q(«$α »)) (ra : Result a) (rb : Result b) : MetaM (Result e) := do
226+ /-- The result of adding two norm_num results. -/
227+ def Result.add {u : Level} {α : Q(Type u)} {a b : Q($α)} (ra : Result q($a)) (rb : Result q($b))
228+ (inst : Q(Add $α) := by exact q(delta% inferInstance)) :
229+ MetaM (Result q($a + $b)) := do
229230 let rec intArm (rα : Q(Ring $α)) := do
230- haveI ' : $e =Q $a + $b := ⟨⟩
231+ assumeInstancesCommute
231232 let ⟨za, na, pa⟩ ← ra.toInt _; let ⟨zb, nb, pb⟩ ← rb.toInt _
232- haveI ' : $f =Q HAdd.hAdd := ⟨⟩
233233 let zc := za + zb
234234 have c := mkRawIntLit zc
235235 haveI ' : Int.add $na $nb =Q $c := ⟨⟩
236- return .isInt rα c zc q(isInt_add (f := $f) (.refl $f) $pa $pb (.refl $c))
237- let rec nnratArm (dsα : Q(DivisionSemiring $α)) : Option (Result _) := do
238- haveI ' : $e =Q $a + $b := ⟨⟩
239- haveI ' : $f =Q HAdd.hAdd := ⟨⟩
236+ return .isInt rα c zc q(isInt_add (.refl _) $pa $pb (.refl $c))
237+ let rec nnratArm (dsα : Q(DivisionSemiring $α)) : MetaM (Result _) := do
238+ assumeInstancesCommute
240239 let ⟨qa, na, da, pa⟩ ← ra.toNNRat' dsα; let ⟨qb, nb, db, pb⟩ ← rb.toNNRat' dsα
241240 let qc := qa + qb
242241 let dd := qa.den * qb.den
@@ -249,10 +248,9 @@ def evalAdd.core {u : Level} {α : Q(Type u)} (e : Q(«$α»)) (f : Q(«$α»
249248 let r1 : Q(Nat.add (Nat.mul $na $db) (Nat.mul $nb $da) = Nat.mul $k $nc) :=
250249 (q(Eq.refl $t1) : Expr)
251250 let r2 : Q(Nat.mul $da $db = Nat.mul $k $dc) := (q(Eq.refl $t2) : Expr)
252- return .isNNRat' dsα qc nc dc q(isNNRat_add (f := $f) (.refl $f) $pa $pb $r1 $r2)
253- let rec ratArm (dα : Q(DivisionRing $α)) : Option (Result _) := do
254- haveI ' : $e =Q $a + $b := ⟨⟩
255- haveI ' : $f =Q HAdd.hAdd := ⟨⟩
251+ return .isNNRat' dsα qc nc dc q(isNNRat_add (.refl _) $pa $pb $r1 $r2)
252+ let rec ratArm (dα : Q(DivisionRing $α)) : MetaM (Result _) := do
253+ assumeInstancesCommute
256254 let ⟨qa, na, da, pa⟩ ← ra.toRat' dα; let ⟨qb, nb, db, pb⟩ ← rb.toRat' dα
257255 let qc := qa + qb
258256 let dd := qa.den * qb.den
@@ -265,25 +263,26 @@ def evalAdd.core {u : Level} {α : Q(Type u)} (e : Q(«$α»)) (f : Q(«$α»
265263 let r1 : Q(Int.add (Int.mul $na $db) (Int.mul $nb $da) = Int.mul $k $nc) :=
266264 (q(Eq.refl $t1) : Expr)
267265 let r2 : Q(Nat.mul $da $db = Nat.mul $k $dc) := (q(Eq.refl $t2) : Expr)
268- return .isRat dα qc nc dc q(isRat_add (f := $f) ( .refl $f ) $pa $pb $r1 $r2)
266+ return .isRat dα qc nc dc q(isRat_add (.refl _ ) $pa $pb $r1 $r2)
269267 match ra, rb with
270268 | .isBool .., _ | _, .isBool .. => failure
271269 | .isNegNNRat dα .., _ | _, .isNegNNRat dα .. => ratArm dα
272270 -- mixing positive rationals and negative naturals means we need to use the full rat handler
273271 | .isNNRat _dsα .., .isNegNat _rα .. | .isNegNat _rα .., .isNNRat _dsα .. =>
274272 -- could alternatively try to combine `rα` and `dsα` here, but we'd have to do a defeq check
275273 -- so would still need to be in `MetaM`.
276- ratArm (←synthInstanceQ q(DivisionRing $α))
274+ let dα ← synthInstanceQ q(DivisionRing $α)
275+ assumeInstancesCommute
276+ ratArm q($dα)
277277 | .isNNRat dsα .., _ | _, .isNNRat dsα .. => nnratArm dsα
278278 | .isNegNat rα .., _ | _, .isNegNat rα .. => intArm rα
279279 | .isNat _ na pa, .isNat sα nb pb =>
280- haveI ' : $e =Q $a + $b := ⟨⟩
281- haveI ' : $f =Q HAdd.hAdd := ⟨⟩
282280 assumeInstancesCommute
283281 have c : Q(ℕ) := mkRawNatLit (na.natLit! + nb.natLit!)
284282 haveI ' : Nat.add $na $nb =Q $c := ⟨⟩
285- return .isNat sα c q(isNat_add (f := $f) ( .refl $f ) $pa $pb (.refl $c))
283+ return .isNat sα c q(isNat_add (.refl _ ) $pa $pb (.refl $c))
286284
285+ attribute [local instance ] monadLiftOptionMetaM in
287286/-- The `norm_num` extension which identifies expressions of the form `a + b`,
288287such that `norm_num` successfully recognises both `a` and `b`. -/
289288@ [norm_num _ + _] def evalAdd : NormNumExt where eval {u α} e := do
@@ -300,7 +299,7 @@ such that `norm_num` successfully recognises both `a` and `b`. -/
300299 | .isNegNNRat _ .., .isNat _ .. | .isNegNNRat _ .., .isNegNat _ ..
301300 | .isNegNNRat _ .., .isNNRat _ .. | .isNegNNRat _ .., .isNegNNRat _ .. =>
302301 guard <|← withNewMCtxDepth <| isDefEq f q(HAdd.hAdd (α := $α))
303- evalAdd.core q($e) q($f) q($a) q($b) ra rb
302+ ra.add rb
304303
305304-- see note [norm_num lemma function equality]
306305theorem isInt_neg {α} [Ring α] : ∀ {f : α → α} {a : α} {a' b : ℤ},
@@ -313,40 +312,41 @@ theorem isRat_neg {α} [Ring α] : ∀ {f : α → α} {a : α} {n n' : ℤ} {d
313312 | _, _, _, _, _, rfl, ⟨h, rfl⟩, rfl => ⟨h, by rw [← neg_mul, ← Int.cast_neg]; rfl⟩
314313
315314attribute [local instance ] monadLiftOptionMetaM in
316- /-- Main part of `evalNeg`. -/
317- def evalNeg.core {u : Level} {α : Q(Type u)} (e : Q(«$α »)) (f : Q(«$α » → «$α »)) (a : Q(«$α »))
318- (ra : Result a) (rα : Q(Ring «$α »)) : MetaM (Result e) := do
319- have : $f =Q Neg.neg := ⟨⟩
320- haveI ' _e_eq : $e =Q -$a := ⟨⟩
315+ /-- The result of subtracting two norm_num results. -/
316+ def Result.neg {u : Level} {α : Q(Type u)} {a : Q($α)} (ra : Result q($a))
317+ (rα : Q(Ring $α) := by exact q(delta% inferInstance)) :
318+ MetaM (Result q(-$a)) := do
321319 let intArm (rα : Q(Ring $α)) := do
322320 assumeInstancesCommute
323321 let ⟨za, na, pa⟩ ← ra.toInt rα
324322 let zb := -za
325323 have b := mkRawIntLit zb
326324 haveI ' : Int.neg $na =Q $b := ⟨⟩
327- return .isInt rα b zb q(isInt_neg (f := $f) ( .refl $f ) $pa (.refl $b))
325+ return .isInt rα b zb q(isInt_neg (.refl _ ) $pa (.refl $b))
328326 let ratArm (dα : Q(DivisionRing $α)) : Option (Result _) := do
329327 assumeInstancesCommute
330328 let ⟨qa, na, da, pa⟩ ← ra.toRat' dα
331329 let qb := -qa
332330 have nb := mkRawIntLit qb.num
333331 haveI ' : Int.neg $na =Q $nb := ⟨⟩
334- return .isRat dα qb nb da q(isRat_neg (f := $f) ( .refl $f ) $pa (.refl $nb))
332+ return .isRat dα qb nb da q(isRat_neg (.refl _ ) $pa (.refl $nb))
335333 match ra with
336334 | .isBool _ .. => failure
337335 | .isNat _ .. => intArm rα
338336 | .isNegNat rα .. => intArm rα
339337 | .isNNRat _dsα .. => ratArm (← synthInstanceQ q(DivisionRing $α))
340338 | .isNegNNRat dα .. => ratArm dα
341339
340+ attribute [local instance ] monadLiftOptionMetaM in
342341/-- The `norm_num` extension which identifies expressions of the form `-a`,
343342such that `norm_num` successfully recognises `a`. -/
344343@ [norm_num -_] def evalNeg : NormNumExt where eval {u α} e := do
345344 let .app (f : Q($α → $α)) (a : Q($α)) ← whnfR e | failure
346345 let ra ← derive a
347346 let rα ← inferRing α
348347 let ⟨(_f_eq : $f =Q Neg.neg)⟩ ← withNewMCtxDepth <| assertDefEqQ _ _
349- evalNeg.core q($e) q($f) q($a) ra rα
348+ haveI ' _e_eq : $e =Q -$a := ⟨⟩
349+ ra.neg
350350
351351-- see note [norm_num lemma function equality]
352352theorem isInt_sub {α} [Ring α] : ∀ {f : α → α → α} {a b : α} {a' b' c : ℤ},
@@ -364,19 +364,18 @@ theorem isRat_sub {α} [Ring α] {f : α → α → α} {a b : α} {na nb nc :
364364 rw [show Int.mul (-nb) _ = _ from neg_mul ..]; exact h₁
365365
366366attribute [local instance ] monadLiftOptionMetaM in
367- /-- Main part of `evalSub`. -/
368- def evalSub.core {u : Level} {α : Q(Type u)} (e : Q(«$α »)) (f : Q(«$α » → «$α » → «$α »))
369- (a b : Q(«$α »)) (rα : Q(Ring «$α »)) (ra : Result a) (rb : Result b) : MetaM (Result e) := do
370- have : $f =Q HSub.hSub := ⟨⟩
371- haveI ' _e_eq : $e =Q $a - $b := ⟨⟩
367+ /-- The result of subtracting two norm_num results. -/
368+ def Result.sub {u : Level} {α : Q(Type u)} {a b : Q($α)} (ra : Result q($a)) (rb : Result q($b))
369+ (inst : Q(Ring $α) := by exact q(delta% inferInstance)) :
370+ MetaM (Result q($a - $b)) := do
372371 let intArm (rα : Q(Ring $α)) := do
373372 assumeInstancesCommute
374373 let ⟨za, na, pa⟩ ← ra.toInt rα; let ⟨zb, nb, pb⟩ ← rb.toInt rα
375374 let zc := za - zb
376375 have c := mkRawIntLit zc
377376 haveI ' : Int.sub $na $nb =Q $c := ⟨⟩
378- return Result.isInt rα c zc q(isInt_sub (f := $f) ( .refl $f ) $pa $pb (.refl $c))
379- let ratArm (dα : Q(DivisionRing $α)) : Option (Result _) := do
377+ return Result.isInt rα c zc q(isInt_sub (.refl _ ) $pa $pb (.refl $c))
378+ let ratArm (dα : Q(DivisionRing $α)) : MetaM (Result _) := do
380379 assumeInstancesCommute
381380 let ⟨qa, na, da, pa⟩ ← ra.toRat' dα; let ⟨qb, nb, db, pb⟩ ← rb.toRat' dα
382381 let qc := qa - qb
@@ -390,16 +389,18 @@ def evalSub.core {u : Level} {α : Q(Type u)} (e : Q(«$α»)) (f : Q(«$α»
390389 let r1 : Q(Int.sub (Int.mul $na $db) (Int.mul $nb $da) = Int.mul $k $nc) :=
391390 (q(Eq.refl $t1) : Expr)
392391 let r2 : Q(Nat.mul $da $db = Nat.mul $k $dc) := (q(Eq.refl $t2) : Expr)
393- return .isRat dα qc nc dc q(isRat_sub (f := $f) ( .refl $f ) $pa $pb $r1 $r2)
392+ return .isRat dα qc nc dc q(isRat_sub (.refl _ ) $pa $pb $r1 $r2)
394393 match ra, rb with
395394 | .isBool .., _ | _, .isBool .. => failure
396395 | .isNegNNRat dα .., _ | _, .isNegNNRat dα .. =>
397396 ratArm dα
398397 | _, .isNNRat _dsα .. | .isNNRat _dsα .., _ =>
399398 ratArm (← synthInstanceQ q(DivisionRing $α))
400- | .isNegNat rα .., _ | _, .isNegNat rα ..
401- | .isNat _ .., .isNat _ .. => intArm rα
399+ | .isNegNat _rα .., _ | _, .isNegNat _rα ..
400+ | .isNat _ .., .isNat _ .. =>
401+ intArm inst
402402
403+ attribute [local instance ] monadLiftOptionMetaM in
403404/-- The `norm_num` extension which identifies expressions of the form `a - b` in a ring,
404405such that `norm_num` successfully recognises both `a` and `b`. -/
405406@ [norm_num _ - _] def evalSub : NormNumExt where eval {u α} e := do
@@ -408,7 +409,7 @@ such that `norm_num` successfully recognises both `a` and `b`. -/
408409 let ⟨(_f_eq : $f =Q HSub.hSub)⟩ ← withNewMCtxDepth <| assertDefEqQ _ _
409410 let ra ← derive a; let rb ← derive b
410411 haveI ' _e_eq : $e =Q $a - $b := ⟨⟩
411- evalSub.core q($e) q($f) q($a) q($b) q($rα) ra rb
412+ ra.sub rb
412413
413414-- see note [norm_num lemma function equality]
414415theorem isNat_mul {α} [Semiring α] : ∀ {f : α → α → α} {a b : α} {a' b' c : ℕ},
@@ -461,19 +462,18 @@ theorem isRat_mul {α} [Ring α] {f : α → α → α} {a b : α} {na nb nc :
461462 (Nat.cast_commute (α := α) db dc).invOf_left.invOf_right.right_comm]
462463
463464attribute [local instance ] monadLiftOptionMetaM in
464- /-- Main part of `evalMul`. -/
465- def evalMul.core {u : Level} {α : Q(Type u)} (e : Q(«$α »)) (f : Q(«$α » → «$α » → «$α »))
466- (a b : Q(«$α »)) (sα : Q(Semiring «$α »)) (ra : Result a) (rb : Result b) : MetaM (Result e) := do
467- haveI ' : $f =Q HMul.hMul := ⟨⟩
468- haveI ' : $e =Q $a * $b := ⟨⟩
469- let rec intArm (rα : Q(Ring $α)) := do
465+ /-- The result of multiplying two norm_num results. -/
466+ def Result.mul {u : Level} {α : Q(Type u)} {a b : Q($α)} (ra : Result q($a)) (rb : Result q($b))
467+ (inst : Q(Semiring $α) := by exact q(delta% inferInstance)) :
468+ MetaM (Result q($a * $b)) := do
469+ let intArm (rα : Q(Ring $α)) := do
470470 assumeInstancesCommute
471471 let ⟨za, na, pa⟩ ← ra.toInt rα; let ⟨zb, nb, pb⟩ ← rb.toInt rα
472472 let zc := za * zb
473473 have c := mkRawIntLit zc
474474 haveI ' : Int.mul $na $nb =Q $c := ⟨⟩
475- return .isInt rα c zc q(isInt_mul (f := $f) ( .refl $f ) $pa $pb (.refl $c))
476- let rec nnratArm (dsα : Q(DivisionSemiring $α)) : Option (Result _) := do
475+ return .isInt rα c zc q(isInt_mul (.refl _ ) $pa $pb (.refl $c))
476+ let nnratArm (dsα : Q(DivisionSemiring $α)) : Option (Result _) := do
477477 assumeInstancesCommute
478478 let ⟨qa, na, da, pa⟩ ← ra.toNNRat' dsα; let ⟨qb, nb, db, pb⟩ ← rb.toNNRat' dsα
479479 let qc := qa * qb
@@ -486,7 +486,7 @@ def evalMul.core {u : Level} {α : Q(Type u)} (e : Q(«$α»)) (f : Q(«$α»
486486 (q(Eq.refl (Nat.mul $na $nb)) : Expr)
487487 have t2 : Q(ℕ) := mkRawNatLit dd
488488 let r2 : Q(Nat.mul $da $db = Nat.mul $k $dc) := (q(Eq.refl $t2) : Expr)
489- return .isNNRat' dsα qc nc dc q(isNNRat_mul (f := $f) ( .refl $f ) $pa $pb $r1 $r2)
489+ return .isNNRat' dsα qc nc dc q(isNNRat_mul (.refl _ ) $pa $pb $r1 $r2)
490490 let rec ratArm (dα : Q(DivisionRing $α)) : Option (Result _) := do
491491 assumeInstancesCommute
492492 let ⟨qa, na, da, pa⟩ ← ra.toRat' dα; let ⟨qb, nb, db, pb⟩ ← rb.toRat' dα
@@ -500,7 +500,7 @@ def evalMul.core {u : Level} {α : Q(Type u)} (e : Q(«$α»)) (f : Q(«$α»
500500 (q(Eq.refl (Int.mul $na $nb)) : Expr)
501501 have t2 : Q(ℕ) := mkRawNatLit dd
502502 let r2 : Q(Nat.mul $da $db = Nat.mul $k $dc) := (q(Eq.refl $t2) : Expr)
503- return .isRat dα qc nc dc q(isRat_mul (f := $f) ( .refl $f ) $pa $pb $r1 $r2)
503+ return .isRat dα qc nc dc q(isRat_mul (.refl _ ) $pa $pb $r1 $r2)
504504 match ra, rb with
505505 | .isBool .., _ | _, .isBool .. => failure
506506 | .isNegNNRat dα .., _ | _, .isNegNNRat dα .. =>
@@ -513,12 +513,12 @@ def evalMul.core {u : Level} {α : Q(Type u)} (e : Q(«$α»)) (f : Q(«$α»
513513 | .isNNRat dsα .., _ | _, .isNNRat dsα .. =>
514514 nnratArm dsα
515515 | .isNegNat rα .., _ | _, .isNegNat rα .. => intArm rα
516- | .isNat mα' na pa, .isNat mα nb pb =>
516+ | .isNat mα' na pa, .isNat mα nb pb => do
517517 haveI ' : $mα =Q by clear! $mα $mα'; apply AddCommMonoidWithOne.toAddMonoidWithOne := ⟨⟩
518518 assumeInstancesCommute
519519 have c : Q(ℕ) := mkRawNatLit (na.natLit! * nb.natLit!)
520520 haveI ' : Nat.mul $na $nb =Q $c := ⟨⟩
521- return .isNat mα c q(isNat_mul (f := $f) ( .refl $f ) $pa $pb (.refl $c))
521+ return .isNat mα c q(isNat_mul (.refl _ ) $pa $pb (.refl $c))
522522
523523/-- The `norm_num` extension which identifies expressions of the form `a * b`,
524524such that `norm_num` successfully recognises both `a` and `b`. -/
@@ -529,7 +529,7 @@ such that `norm_num` successfully recognises both `a` and `b`. -/
529529 guard <|← withNewMCtxDepth <| isDefEq f q(HMul.hMul (α := $α))
530530 haveI ' : $f =Q HMul.hMul := ⟨⟩
531531 haveI ' : $e =Q $a * $b := ⟨⟩
532- evalMul.core q($e) q($f) q($a) q($b) q($sα) ra rb
532+ ra.mul rb
533533
534534theorem isNNRat_div {α : Type u} [DivisionSemiring α] : {a b : α} → {cn : ℕ} → {cd : ℕ} →
535535 IsNNRat (a * b⁻¹) cn cd → IsNNRat (a / b) cn cd
@@ -718,3 +718,5 @@ end NormNum
718718end Meta
719719
720720end Mathlib
721+
722+ open Mathlib.Meta.NormNum
0 commit comments