Zulip Chat Archive
Stream: metaprogramming / tactics
Topic: LocalDecl not recognized in MVar
nrs (Dec 21 2024 at 01:16):
In the following #mwe, I declare an fvar sig
of type Signature
, and then a goal of type SigSingleton sig
. However, the goal created a dagger name instead of using the sig
I declared. What might be causing this? (also, let goal <- mkFreshExprMVar (<- TermElabM.run' do elabTerm (<- ...
seems somewhat verbose, is this idiomatic?)
import Mathlib
open Lean Meta Elab Command Term
structure Signature where
α : Type
β : α -> Type
inductive SigSingleton (sig : Signature)
| mk : SigSingleton sig
def c : CoreM Unit := do
let result <- MetaM.run' (α := Unit) do
withLocalDecl `sig .default (mkConst `Signature) fun _ => do
let goal <- mkFreshExprMVar (<- TermElabM.run' do elabTerm (<- `(SigSingleton sig)) (Expr.sort levelOne))
goal.mvarId!.withContext do
(<- getLCtx).forM fun decl => do
logInfo f!"localdecl: name: {decl.userName}; type: {<- inferType decl.toExpr}"
#eval c
-- localdecl: name: sig; type: Signature
-- unknown constant 'sig✝'
nrs (Dec 21 2024 at 01:24):
ah, manually declaring the expr with let goal <- mkFreshExprMVar <| mkApp (.const ``SigSingleton .nil) (.const ``sig .nil)
seems to fix the issue. Is the call to TermElabM.run'
putting the sig
name out of context? If so, is there a way to pass the relevant context?
Eric Wieser (Dec 21 2024 at 01:42):
Did you mean to write fun sig
instead of fun _
?
Eric Wieser (Dec 21 2024 at 01:42):
I think this is a better way to write what you want:
open Qq
def c : CoreM Unit := do
let result <- MetaM.run' (α := Unit) do
withLocalDeclQ `sig .default q(Signature) fun sig => do
let goal <- mkFreshExprMVarQ q(SigSingleton $sig)
goal.mvarId!.withContext do
(<- getLCtx).forM fun decl => do
logInfo m!"localdecl: name: {Expr.fvar decl.fvarId}; type: {<- inferType decl.toExpr}"
nrs (Dec 21 2024 at 01:44):
Did you mean to write
fun sig
instead offun _
?
Oh I didn't realize I needed to explicitly pass the Expr
variable, I thought it would be recognized through it's LocalDecl name sig
, thanks! And thanks a lot for that example, very helpful!!
Eric Wieser (Dec 21 2024 at 02:04):
nrs said:
I thought it would be recognized through it's LocalDecl name
sig
,
I think the sig
inside `( )
has hygiene considerations, so does not match the variable you asked to be called `sig
Eric Wieser (Dec 21 2024 at 02:05):
In your version you could have used `(SigSingleton $(sig.toSyntax))
I think
Kyle Miller (Dec 21 2024 at 02:06):
def c : CoreM Unit := do
let result <- MetaM.run' (α := Unit) do
let sig := mkIdent `sig
withLocalDecl sig.getId .default (mkConst `Signature) fun _ => do
let goal <- mkFreshExprMVar (<- TermElabM.run' do elabTerm (<- `(SigSingleton $sig)) (Expr.sort levelOne))
goal.mvarId!.withContext do
(<- getLCtx).forM fun decl => do
logInfo f!"localdecl: name: {decl.userName}; type: {<- inferType decl.toExpr}"
#eval c
-- localdecl: name: sig; type: Signature
nrs (Dec 21 2024 at 02:07):
Eric Wieser
I think the
sig
inside () has hygiene considerations, so does not match the variable you asked to be called sig
ah makes a lot of sense! thanks a lot! haven't encountered Qq
before, am browsing around a bit to see what it's about, thanks for that reference too
Kyle Miller (Dec 21 2024 at 02:08):
All this Meta.run
and TermElabM.run
is fairly nonstandard. Why not stick with TermElabM?
def c : TermElabM Unit := do
let result <- do
let sig := mkIdent `sig
withLocalDeclD sig.getId (mkConst `Signature) fun _ => do
let goal <- mkFreshExprMVar (<- elabTerm (<- `(SigSingleton $sig)) none)
goal.mvarId!.withContext do
(<- getLCtx).forM fun decl => do
logInfo f!"localdecl: name: {decl.userName}; type: {<- inferType decl.toExpr}"
#eval c
-- localdecl: name: sig; type: Signature
Eric Wieser (Dec 21 2024 at 02:09):
Though using Qq lets you stay in MetaM
without needing TermElabM
at all!
Kyle Miller (Dec 21 2024 at 02:09):
Here's the core Lean version of what the Qq version is doing:
def c : MetaM Unit := do
let result <- do
withLocalDeclD `sig (mkConst `Signature) fun sig => do
let goal <- mkFreshExprMVar (<- mkAppM ``SigSingleton #[sig])
goal.mvarId!.withContext do
(<- getLCtx).forM fun decl => do
logInfo f!"localdecl: name: {decl.userName}; type: {<- inferType decl.toExpr}"
#eval c
-- localdecl: name: sig; type: Signature
nrs (Dec 21 2024 at 02:10):
@Kyle Miller hm right thanks a lot for the examples, these are extremely useful, highly appreciated! I'm debugging why a metavariable is failing to isDefEq
by virtue of being unassignable, so I'm trying to simulate the metavar context in MetaM
. Should I stick to TermElabM
?
Kyle Miller (Dec 21 2024 at 02:10):
though mkAppM
is doing checking at runtime rather than compile time
Kyle Miller (Dec 21 2024 at 02:12):
If you think you have a strong enough understanding to debug Lean by simulating part of it, and you fully understand that using these run functions means that you're getting some default configuration, then go ahead, but I imagine there are easier ways to figure out what's going on.
nrs (Dec 21 2024 at 02:18):
hm right... I will instead build a super simplified example with the references provided here for educational purposes and will go back to trying to find a different way to debug that, thanks for the recommendations!
Last updated: May 02 2025 at 03:31 UTC