Zulip Chat Archive
Stream: general
Topic: grind on a new UInt type
Alexander Bentkamp (Dec 18 2025 at 11:41):
I would like to create a copy of UInt64, which I call USize64. How can I set grind up to work on it just as well as on UInt64? Here is an example of what I would like to achieve:
set_option trace.grind.debug true
/- This works: -/
example {i} :
UInt64.toNat i < UInt64.toNat 3 →
UInt64.toNat 4 + UInt64.toNat i < 100 :=
by grind only => done
/- A copy of UInt64 -/
structure USize64 where ofUInt64 :: toUInt64 : UInt64
instance {n} : OfNat USize64 n := ⟨⟨OfNat.ofNat n⟩⟩
def USize64.toNat (n : USize64) : Nat := UInt64.toNat n.toUInt64
/- The same example fails on my new type: -/
example {i} :
USize64.toNat i < USize64.toNat 3 →
USize64.toNat 4 + USize64.toNat i < 100 :=
by grind only => done
I have tried to instantiate the Lean.Grind.ToInt type classes, but without success.
Robin Arnez (Dec 18 2025 at 22:20):
I think the relevant stuff is in Init.GrindInstances.Ring.UInt lines 281-318 and lines 45-73
and Init.GrindInstances.ToInt lines 248-280
Alexander Bentkamp (Dec 19 2025 at 08:07):
I think I tried to add all of these before. Is there a way to get debug output from grind that would tell me exactly which of these instances is used?
Robin Arnez (Dec 19 2025 at 19:25):
Oh right in this case this is grind using the seval simproc UInt64.reduceToNat from here
Alexander Bentkamp (Dec 19 2025 at 19:27):
Oh. That's great to know! How did you find out?
Alexander Bentkamp (Dec 19 2025 at 21:01):
And, more importantly, can I add custom simprocs to grind? I saw an older thread that you cannot. Is this still the case?
Robin Arnez (Dec 19 2025 at 21:09):
You can, kinda, but I'd not recommend doing this for anything other than evaluation simprocs:
import Lean
/-- A copy of UInt64 -/
structure USize64 where ofUInt64 :: toUInt64 : UInt64
instance {n} : OfNat USize64 n := ⟨⟨OfNat.ofNat n⟩⟩
def USize64.toNat (n : USize64) : Nat := UInt64.toNat n.toUInt64
open Lean Meta in
simproc [seval] USize64.reduceToNat (USize64.toNat _) := fun e => do
let_expr USize64.toNat n := e | return .continue
let some (n, _) ← getOfNatValue? n ``USize64 | return .continue
return .done { expr := toExpr n.toUInt64.toNat }
/-- Works -/
example {i} : USize64.toNat i < USize64.toNat 3 → USize64.toNat 4 + USize64.toNat i < 100 := by
grind only => done
Alexander Bentkamp (Dec 19 2025 at 22:22):
Wow, that's great! Thank you!
Last updated: Dec 20 2025 at 21:32 UTC