Zulip Chat Archive
Stream: general
Topic: With notation for context managers
Eric Wieser (Aug 29 2025 at 18:16):
Eric Wieser said:
Though maybe the answer is "frame everything in a way suitable for
with", just as we already do forfor
I guess this also reveals a hack for using for to implement with
Eric Wieser (Aug 29 2025 at 18:23):
import Lean
import Qq
open Lean Meta Qq
section with_notation
/-- Typeclass to provide `with ctx as v` notation in the monad `m`, where `ctx : ρ` and `v : α`. -/
class WithNotation (m : Type → Type) (ρ : Type) (α : outParam Type) where
with_ {β : Type _} [Monad m] (xs : ρ) (f : α → m (ForInStep β)) : m β
structure WithHandler (α) where handler : α
instance [WithNotation m ρ α] : ForIn m (WithHandler ρ) α where
forIn ctx v f := WithNotation.with_ ctx.handler fun a => f a v
macro "with" t:term "as" v:ident "do" body:doSeq : doElem => `(doElem| for $v in WithHandler.mk $t do $body)
end with_notation
/-! Example usage -/
structure LocalDeclCtx where
name : Name
bi : BinderInfo
ty : Expr
instance : WithNotation Lean.Meta.MetaM LocalDeclCtx Expr where
with_ ctx f := do
return (← withLocalDecl ctx.name ctx.bi ctx.ty f).value
run_meta do
with LocalDeclCtx.mk `foo default q(Nat) as v do
Lean.logInfo v
Joe Hendrix (Aug 29 2025 at 18:24):
There may be a generic way to handle this for callbacks in monads with call/cc, but I think otherwise interface changes would be needed.
Indeed, that's a nice observation on using for.
Eric Wieser (Aug 29 2025 at 18:44):
Another example:
structure TheReaderOf (α : Type) where
val : α → α
abbrev theReader := @TheReaderOf.mk
instance [MonadWithReaderOf ρ m] : WithNotation m (TheReaderOf ρ) Unit where
with_ ctx f := do
return (← withTheReader ρ ctx.val (f ())).value
#eval show IO Unit from ReaderT.run (do
with theReader (fun x : Nat => x + 1) as _x do
IO.println s!"{← read}"
) (1 : Nat)
Jovan Gerbscheid (Aug 29 2025 at 18:54):
That is so cool! And the as clause could be made optional for cases like withReader, so that it would just be with ... do ...
Joe Hendrix (Aug 29 2025 at 19:39):
That's pretty nice. Syntactically, it seems like it may be good to match let if, with let x := do.
Eric Wieser (Aug 29 2025 at 20:02):
Jovan Gerbscheid said:
That is so cool! And the
asclause could be made optional for cases likewithReader, so that it would just bewith ... do ...
I tried this and got annoyed with the syntax ambiguity, but I imagine it's not too hard to fix
Eric Wieser (Aug 29 2025 at 20:02):
A particularly useful context manager to have would be python's ExitStack, which seems more work to build here
Notification Bot (Aug 29 2025 at 20:07):
8 messages were moved here from #general > Discussion: Lean FRO roadmap, year 3 by Eric Wieser.
Jovan Gerbscheid (Aug 29 2025 at 20:54):
Wouldn't it be possible to make it work without any special type class, but just passing the function directly? So
with withLocalDecl `foo default q(Nat) as v do
Lean.logInfo v
and
#eval show IO Unit from ReaderT.run (do
with withReader (fun x : Nat => x + 1) do
IO.println s!"{← read}"
) (1 : Nat)
Eric Wieser (Aug 29 2025 at 21:15):
I think there's value in the type wrapper, just as there is for for
Jovan Gerbscheid (Aug 29 2025 at 21:23):
With for the actual implementation is usually quitecomplicated, because of it has to be recursive. With with, I want to be able to do this using any function that has the same type as withReader (fun _ => _), without needing to define a separate structure for each function.
Eric Wieser (Aug 29 2025 at 23:11):
I guess the question is whether you want to be able to write things like with someFileHandle for automatic closing, etc
Jovan Gerbscheid (Aug 29 2025 at 23:14):
Are you're saying that this kind of file handling can't be described by a function that has a similar type to withLocalDecl?
Eric Wieser (Aug 29 2025 at 23:15):
No, I'm saying that you're losing the option to have an implicit conversion happen. You could also imagine a world where you have to write for x in myArray.iter instead of for x in myArray, where ForIn also only works directly with a (complex) function type
Last updated: Dec 20 2025 at 21:32 UTC