Zulip Chat Archive
Stream: lean4
Topic: Lean 4 version of eval_expr
Notification Bot (Dec 10 2021 at 09:06):
Tomas Skrivan has marked this topic as unresolved.
Tomas Skrivan (Dec 10 2021 at 09:10):
Ok I'm confused on how to use it. I want to synthesize an instance of a class and extract one field. Here is my attempt:
import Lean
open Lean Elab Meta Term
#eval ((do
let E ← mkAppM `Add #[mkConst `Nat]
let e ← synthInstance E
let add_expr ← whnf (← mkProj `add 0 e)
let T ← whnfD (← inferType add_expr)
IO.println add_expr
IO.println T.isConst -- this is false .. so I can't use evalExpr?
let add ← evalExpr (Nat → Nat → Nat) (???) add_expr --- What should be `typeName`?
) : TermElabM Unit)
It looks like that evalExpr
can't be used in this scenario :/
Mario Carneiro (Dec 10 2021 at 09:14):
I think you can just make def Foo := Nat -> Nat -> Nat
and pass `Foo
for typeName
Tomas Skrivan (Dec 10 2021 at 09:15):
Nope, getting unexpected type at evalExpr
Mario Carneiro (Dec 10 2021 at 09:17):
you can also skip evalExpr
and use evalConst
directly
Tomas Skrivan (Dec 10 2021 at 09:18):
But where it the dependence on add_expr
?
Mario Carneiro (Dec 10 2021 at 09:19):
?
Mario Carneiro (Dec 10 2021 at 09:19):
the code for elabEval
, for example, contains a use of evalConst
for a function type
Tomas Skrivan (Dec 10 2021 at 09:25):
In the code above:
- E
- expression for Add Nat
- e
- expression for instance of Add Nat
- add_expr
- expression for Nat.add
- T
- expression for Nat -> Nat -> Nat
I want to somehow convert add_expr : Expr
to an actual element of Nat -> Nat -> Nat
.
Mario Carneiro (Dec 10 2021 at 09:25):
Here's an adaptation of the elabEval
code:
#eval show TermElabM Unit from do
let E ← mkAppM `Add #[mkConst `Nat]
let e ← synthInstance E
let env ← getEnv
let opts ← getOptions
try
let type ← inferType e
let decl := Declaration.defnDecl {
name := `_bla
levelParams := []
type := type
value := e
hints := ReducibilityHints.opaque
safety := DefinitionSafety.unsafe
}
Term.ensureNoUnassignedMVars decl
addAndCompile decl
let f ← evalConst (Nat → Nat → Nat) `_bla
IO.println (f 1 2)
finally setEnv env
Gabriel Ebner (Dec 10 2021 at 09:33):
If you're willing to (import / copy) from mathlib4, we have a slightly nicer API for evalExpr: https://github.com/leanprover-community/mathlib4/blob/e59238956369b84c3b506ef49ef7e5ceada183e5/Mathlib/Tactic/RunTac.lean#L15-L16
def mkArrow (a b : Expr) : Expr :=
mkForall Name.anonymous BinderInfo.default a b
#eval show TermElabM _ from do
let e ← synthInstance (← mkAppM `Add #[mkConst `Nat])
let f ← unsafe evalExpr (Nat → Nat → Nat)
(mkArrow (mkConst ``Nat) (mkArrow (mkConst ``Nat) (mkConst ``Nat))) e
return f 1 2
Tomas Skrivan (Dec 10 2021 at 09:34):
Thanks a lot! Is there some documentation/part of a paper about the elaborator? It is a part of Lean I still have no clue about.
Mario Carneiro (Dec 10 2021 at 09:35):
Here's that code again in a more convenient package:
unsafe def withEvalExpr [Monad m] [MonadError m] [MonadFinally m]
[MonadEnv m] [MonadOptions m] [MonadLiftT TermElabM m]
(α : Type) (e : Expr) (f : α → m Unit) : m Unit := do
let env ← getEnv
let opts ← getOptions
try
let type ← (inferType e : TermElabM _)
let decl := Declaration.defnDecl {
name := `_bla
levelParams := []
type := type
value := e
hints := ReducibilityHints.opaque
safety := DefinitionSafety.unsafe
}
Term.ensureNoUnassignedMVars decl
addAndCompile decl
f (← evalConst α `_bla)
finally setEnv env
#eval show TermElabM Unit from do
let E ← mkAppM `Add #[mkConst `Nat]
let e ← synthInstance E
withEvalExpr (Nat → Nat → Nat) e fun f => do
IO.println (f 1 2)
Mario Carneiro (Dec 10 2021 at 09:36):
not sure how this compares to the mathlib4 version
Mario Carneiro (Dec 10 2021 at 09:36):
no paper, it's the wild west
Mario Carneiro (Dec 10 2021 at 09:42):
yeah, the mathlib4 version is better, use that
Last updated: Dec 20 2023 at 11:08 UTC