Zulip Chat Archive

Stream: metaprogramming / tactics

Topic: modifying local context in MetaM


Tomas Skrivan (May 27 2024 at 12:09):

I would like to have a variant of MetaM monad that can modify the local context. I find passing local context around or working with continuation(e.g. lambdaTelescope) a bit cumbersome sometimes.

Effectively instead of working with

abbrev MetaM  := ReaderT Context $ StateRefT State CoreM

I would like to work with

abbrev MetaLCtxM  := StateT Context $ StateRefT State CoreM

Is this a good/bad idea? Is this done in core Lean in some capacity?


Using this monad I would like to write code like

def lambdaIntro (e : Expr) : MetaLCtxM (Expr × Array Expr) := do
  Meta.lambdaTelescope e fun xs e' => do
    let ctx  getThe ContextCtx
    fun _ _ => return ((e',xs), ctx)

open Lean Meta Qq in
#eval show MetaLCtxM Unit from do
  let e := q(fun a b => a + b + 42)

  let (b, xs)  lambdaIntro e

  IO.println s!"lambda body: {← ppExpr b}"
  IO.println s!"lambda vars: {← liftM <| xs.mapM ppExpr}"
  IO.println s!"lambda: {← ppExpr (← mkLambdaFVars xs b)}"

My application is a tactic dealing with a big expression with lots of let bindings. I want to just keep on collecting (let) free variables and not worry about passing around the local context.


Here is my current attempt at setting up this monad. My main concern is the instance MonadControl MetaM MetaLCtxM, not sure if I got it right and I just hacked the code together until it typechecks.

code

Eric Wieser (May 27 2024 at 14:16):

In #5863 (here) my solution to this (thanks I think to @Kyle Miller) was to work in ContT to transform the continuations back into a monad

Eric Wieser (May 27 2024 at 14:17):

But that ran into the rather thorny #5897 (discussed here), which found that you cant really make ContT support throw without running into issues with catch.

Tomas Skrivan (May 27 2024 at 16:18):

Using ContT is a great idea! I will play around with it.


Last updated: May 02 2025 at 03:31 UTC