Zulip Chat Archive
Stream: general
Topic: How to check whether a term is (0: Nat)?
Dexin Zhang (Mar 08 2025 at 16:07):
t.isConstOf ``Nat.zero
doesn't work...
import Lean
open Lean Meta Elab Tactic
elab "test" t:term : tactic => do
let t ← whnf (← elabTerm t none)
logInfo m!"{t.isConstOf ``Nat.zero}"
example : False := by
test 0 -- false
Markus Himmel (Mar 08 2025 at 16:10):
How about this:
import Lean
open Lean Meta Elab Tactic
elab "test" t:term : tactic => do
let o ← getOfNatValue? (← elabTerm t none) `Nat
let isZero := o.any (·.1 = 0)
logInfo m!"{isZero}"
example : False := by
test 0 -- true
test 1 -- false
test (0 : Int) -- false
Markus Himmel (Mar 08 2025 at 16:12):
Though I'm not sure if it's exactly what exactly you want. The code I posted returns false
for test Nat.zero
.
Dexin Zhang (Mar 08 2025 at 16:14):
Thanks! I think getNatValue?
is enough for me
Dexin Zhang (Mar 08 2025 at 16:14):
Or there might be a nicer way?
Markus Himmel (Mar 08 2025 at 16:15):
This could also work for you:
import Lean
open Lean Meta Elab Tactic
elab "test" t:term : tactic => do
let t ← elabTerm t none
let b ← isDefEq t (.const `Nat.zero [])
logInfo m!"{b}"
example : False := by
test 0 -- true
test 1 -- false
test (0 : Int) -- false
test Nat.zero -- true
Aaron Liu (Mar 08 2025 at 16:15):
Why do you need this?
Dexin Zhang (Mar 08 2025 at 16:19):
Aaron Liu said:
Why do you need this?
I'm writing a tactic that process terms of xxx n
(xxx : Nat → Type
), but if it's xxx 0
I can do some special stuffs
Dexin Zhang (Mar 08 2025 at 16:20):
I find getRawNatValue?
exactly what I want
elab "test" t:term : tactic => do
let t ← whnf (← elabTerm t none)
logInfo m!"{getRawNatValue? t == some 0}"
example : False := by
test 0 -- true
Aaron Liu (Mar 08 2025 at 16:52):
I would suggest something like this
import Lean
open Lean Meta Elab Term
def test (stx : Syntax) : TermElabM Bool := do
let t ← elabTerm stx (some Nat.mkType)
withNewMCtxDepth (isDefEq t (mkNatLit 0))
Kyle Miller (Mar 08 2025 at 18:02):
The issue here is that elabTerm
is only initializing term elaboration. There are still pending elaboration problems (the fact that it is a Nat
will only be resolved later, once default instances are considered).
Kyle Miller (Mar 08 2025 at 18:03):
@Aaron Liu's isDefEq
solution appears to work because it's assigning metavariables (the instances are assignable)
Kyle Miller (Mar 08 2025 at 18:04):
Edit: actually, it looks like you were using the Tactic version of elabTerm
in your initial post, which does have a step to complete all elaboration problems. I have to check what's going on.
Kyle Miller (Mar 08 2025 at 18:08):
Ok, it looks like you are already working with getRawNatValue?
and figured out the solution (I should read the whole thread before commenting). There's also Expr.rawNatLit?
that would work here, which does basically the same thing. I changed elabTerm
to Tactic.elabTerm
to reduce risk of confusion about which one you're using:
import Lean
open Lean Meta Elab Tactic
elab "test" t:term : tactic => do
let t ← whnf (← Tactic.elabTerm t none)
let isZero := t.rawNatLit? == some 0
logInfo m!"{isZero}"
example : False := by
test 0 -- true
Kyle Miller (Mar 08 2025 at 18:14):
If you're looking for a natural number literal, I believe the correct answer is docs#Lean.Meta.getNatValue?
elab "test" t:term : tactic => do
let t ← Tactic.elabTerm t none
let isZero := (← getNatValue? t) == some 0
logInfo m!"{isZero}"
I would strongly suggest not using whnf
or isDefEq
unless you do indeed want to reduce an expression to a literal, potentially performing an expensive calculation.
Eric Wieser (Mar 09 2025 at 23:41):
(deleted)
loogle (Mar 09 2025 at 23:41):
:exclamation: unknown identifier 'Expr'
Did you mean Nat.Linear.Expr -> Option Nat
, Nat.SOM.Expr -> Option Nat
, or something else?
Eric Wieser (Mar 09 2025 at 23:41):
@loogle Lean.Expr -> Option Nat
loogle (Mar 09 2025 at 23:41):
:search: Lean.Expr.nat?, Lean.Expr.rawNatLit?, and 8 more
Eric Wieser (Mar 09 2025 at 23:42):
Is there a description anywhere of how all these differ?
Eric Wieser (Mar 09 2025 at 23:42):
@loogle Lean.Expr -> Lean.MetaM Nat
loogle (Mar 09 2025 at 23:43):
:search: Lean.Meta.getExpectedNumArgs, Lean.Meta.NormCast.countCoes, and 4 more
Aaron Liu (Mar 09 2025 at 23:44):
Why would you need MetaM
?
Eric Wieser (Mar 09 2025 at 23:48):
That was a bad loogle query guess, but I think docs#getNatValue? is in metam
Aaron Liu (Mar 09 2025 at 23:48):
Eric Wieser said:
Is there a description anywhere of how all these differ?
I'll type something up
Aaron Liu (Mar 10 2025 at 00:24):
Here
Last updated: May 02 2025 at 03:31 UTC