Zulip Chat Archive

Stream: metaprogramming / tactics

Topic: How to make a term of `OfNat.ofNat i : Fin (n + 1)` legally?


Dexin Zhang (Sep 26 2025 at 14:57):

I wrote the following code:

open Lean in
/-- Create an expression of `OfNat.ofNat i : Fin (n + 1)`. -/
def mkOfNat (i : ) (n : Expr) : Expr :=
  mkApp3 (.const ``OfNat.ofNat [0]) (mkApp (.const ``Fin []) (mkNatAdd n (mkNatLit 1))) (mkNatLit i)
    (mkApp3 (.const ``Fin.instOfNat []) (mkNatAdd n (mkNatLit 1))
      (mkApp (.const ``Nat.instNeZeroSucc []) n) (mkNatLit i))

open Lean Meta in
#eval do
  let e := mkOfNat 1 (mkNatLit 3)
  logInfo m!"{e}" -- OfNat.ofNat 1
  logInfo m!"{← getOfNatValue? e ``Fin}" -- none

It does create e as OfNat.ofNat 1 : Fin 3, but the pretty printer shows it as OfNat.ofNat 1, not 1. Also, when I try to use getOfNatValue? to extract the value of e, it fails.

Aaron Liu (Sep 26 2025 at 14:59):

mkRawNatLit

Henrik Böving (Sep 26 2025 at 14:59):

When you try to imitate terms built by the elaborator I would suggest simply looking at what the elaborator did:

variable (n : Nat)

set_option pp.explicit true in
#check (1 : Fin (n + 1))

Dexin Zhang (Sep 26 2025 at 15:00):

Aaron Liu said:

mkRawNatLit

Thanks, it really works!

Dexin Zhang (Sep 26 2025 at 15:01):

Henrik Böving said:

When you try to imitate terms built by the elaborator I would suggest simply looking at what the elaborator did:

variable (n : Nat)

set_option pp.explicit true in
#check (1 : Fin (n + 1))

Thanks, I did try this before, but I don't know what causes the difference then (which turns out to be mkNatLit and mkRawNatLit).


Last updated: Dec 20 2025 at 21:32 UTC