Zulip Chat Archive
Stream: general
Topic: creating lambda without tactic
Zesen Qian (Jul 30 2018 at 16:02):
meta programming problem: So I have a function body represented as expr -> expr
, which receives a reference to the argument, and return the body. Is it possible to abstract the argument away(that is, wrap it with a lambda) and get the anonymous function back as expr
?
Zesen Qian (Jul 30 2018 at 16:02):
I might have been blur about expr
and pexpr
, but I hope that won't cause too much confusion.
Jeremy Avigad (Jul 30 2018 at 19:10):
Look in init/meta/expr.lean
. The trick is to create an expr
with a local constant, use abstract_local
to replace it by an index, and then bind it.
My experiments follow. In the first example, I used a local variable in the context. For some reason, bind_lambda
didn't work in that case (the abstracted variable did not get the right type), so I did it by hand. In the second example, I made a fresh local variable.
open tactic example (f : nat → nat) (x : nat) : nat → nat := by do f' ← get_local `f, x' ← get_local `x, let e := expr.app f' x', trace e, -- e is the expression f x -- let e' := expr.bind_lambda e x', -- this didn't work nt ← to_expr ``(nat), let e' := expr.lam `x binder_info.default nt (e.abstract_local x'.local_uniq_name), trace e', -- e' is the expression λ (x : ℕ), f x exact e' example (f : nat → nat) : nat → nat := by do f' ← get_local `f, nt ← to_expr ``(nat), x' ← mk_local' `x binder_info.default nt, e ← to_expr ``(%%f' %%x'), trace e, -- e is the expression f x let e' := expr.bind_lambda e x', trace e', -- e' is the expression λ (x : ℕ), f x exact e'
Zesen Qian (Jul 30 2018 at 19:30):
Thank you jeremy. But it seems tactic
is still used in both cases? Specifically, you used mk_local
. It seems quite hard to do this without tactic monad?
Zesen Qian (Jul 30 2018 at 19:32):
yeah I think I shouldn't be bother by using tactic
.
Zesen Qian (Jul 30 2018 at 19:33):
I looked in the definition of mk_local
and really, mk_fresh_name
is all I need from the tactic
.
Simon Hudon (Jul 30 2018 at 19:49):
Why is it important to not have the tactic monad?
Zesen Qian (Jul 30 2018 at 19:52):
because this is a proof that in principle can be exclusively derived from a data structure, without looking at the environment.
Zesen Qian (Jul 30 2018 at 19:54):
but anyway, the current solution is good enough, I only need a fresh name from the tactic
monad, so that's minimal side effect.
Jeremy Avigad (Jul 30 2018 at 22:36):
If you are building expressions entirely from scratch, you can make up your own unique name if you want. But expr
is meta
, so if you want to stay entirely within the logic, you have to define your own type of expressions.
Zesen Qian (Jul 30 2018 at 22:38):
I'm actually thinking about using pexpr.var : nat -> pexpr
which is de-bruijn index. So I don't have to worry about all the details of local_const
. I plan to construct the pexpr
as a pure function of the LSEC proof, and elaborate the huge proof altogether.
Zesen Qian (Jul 30 2018 at 22:47):
@Jeremy Avigad yeah but if I do that we still need a conversion from my custom expr to the lean expr
.
Jeremy Avigad (Jul 30 2018 at 22:52):
If you are building Lean expressions, don't hesitate to use the tactic framework. You will probably need constants from the environment anyway, and your code will be easier to debug if you elaborate expressions piece by piece.
Last updated: Dec 20 2023 at 11:08 UTC