Zulip Chat Archive
Stream: metaprogramming / tactics
Topic: constructing expressions
Jon Eugster (May 22 2024 at 08:43):
I am playing around with constructing Expr
's manually.
What am I doing wrong with the following example, why are x
and y
not defeq?
import Lean
import Mathlib.Init.Function
open Lean Meta Function
def f : Prop → Prop := fun n => n
-- def Bijective (f : α → β) :=
-- Injective f ∧ Surjective f
def test : MetaM Unit := do
let x : Expr := (.app (.const ``Bijective [1, 1]) (.const ``f []))
let y : Expr := (mkAppN (.const ``And []) #[(.app (.const ``Injective [1, 1]) (.const ``f [])), (.app (.const ``Surjective [1, 1]) (.const ``f []))])
dbg_trace x -- Function.Bijective.{1, 1} f
dbg_trace y -- And (Function.Injective.{1, 1} f) (Function.Surjective.{1, 1} f)
dbg_trace (← isDefEq x y) -- false
#eval test
Anand Rao Tadipatri (May 22 2024 at 09:50):
It might be that the expressions are not constructed correctly with all the implicit parameters filled in. It seems to work when using docs#Lean.Meta.mkAppM instead of the constructor docs#Lean.Expr.app.
Damiano Testa (May 22 2024 at 10:19):
I find that building Expr
"by hand" is always very brittle. Try
dbg_trace (← whnf x)
dbg_trace (← whnf y)
to get some more insight on what the difference might be. :smile:
Jon Eugster (May 22 2024 at 10:20):
Thanks! mkAppM
was indeed what I needed to figure out how things work. And the implicit arguments are indeed what I missed. This works now:
def test : MetaM Unit := do
let x : Expr := (mkAppN (.const ``Bijective [1, 1]) #[(.sort 0), (.sort 0), (.const ``f [])])
let y : Expr := (mkAppN (.const ``And []) #[(mkAppN (.const ``Injective [1, 1]) #[(.sort 0), (.sort 0), (.const ``f [])]), (mkAppN (.const ``Surjective [1, 1]) #[(.sort 0), (.sort 0), (.const ``f [])])])
dbg_trace x
dbg_trace y
dbg_trace (← isDefEq x y)
Jon Eugster (May 22 2024 at 10:24):
Damiano Testa said:
Try
dbg_trace (← whnf x) dbg_trace (← whnf y)
to get some more insight on what the difference might be. :smile:
Indeed, that showed
fun {β : Type} (f_1 : f -> β) => And (Function.Injective.{1, 1} f β f_1) (Function.Surjective.{1, 1} f β f_1)
vs.
And (Function.Injective.{1, 1} f) (Function.Surjective.{1, 1} f)
Damiano Testa said:
I find that building
Expr
"by hand" is always very brittle.
#xy-ing the problem I want to figure out if two Expr
are definitional equivalent up to renaming of fvar
s and therefore wanted to understand Expr
s better. I assume there is no existing function doing that already?
Jannis Limperg (May 22 2024 at 12:44):
An expression e
with fvars h1 : T1
, ..., hn : Tn
is equivalent to a function λ (h1 : T1) ... (hn : Tn), e
. If you perform this transformation for your two expressions and then check for defeq, the names of the functions' arguments don't matter, so you should get what you want.
Kyle Miller (May 23 2024 at 15:27):
An assumption for isDefEq
is that the terms are type correct. You can use Meta.check
to raise an error if they're not.
def test : MetaM Unit := do
let x : Expr := (.app (.const ``Bijective [1, 1]) (.const ``f []))
let y : Expr := (mkAppN (.const ``And []) #[(.app (.const ``Injective [1, 1]) (.const ``f [])), (.app (.const ``Surjective [1, 1]) (.const ``f []))])
Meta.check x -- error
Meta.check y
dbg_trace x
dbg_trace y
dbg_trace (← isDefEq x y)
#eval test
/--
application type mismatch
@Function.Bijective f
argument
f
has type
Prop → Prop : Type
but is expected to have type
Type : Type 1
-/
Kyle Miller (May 23 2024 at 15:30):
There are some app builder meta functions to help fill in all the implicit arguments for you:
def test : MetaM Unit := do
let fe : Expr := .const ``f []
let x : Expr ← mkAppM ``Bijective #[fe]
let y : Expr ← mkAppM ``And #[← mkAppM ``Injective #[fe], ← mkAppM ``Surjective #[fe]]
Meta.check x
Meta.check y
dbg_trace x
dbg_trace y
dbg_trace (← isDefEq x y)
#eval test
/--
Function.Bijective.{1, 1} Prop Prop f
And (Function.Injective.{1, 1} Prop Prop f) (Function.Surjective.{1, 1} Prop Prop f)
true
-/
Kyle Miller (May 23 2024 at 15:31):
Could you #xy a bit further @Jon Eugster? What's the application where you have exprs with different fvars? Are they exprs in different local contexts? or the same context? Might there be metavariables too?
Last updated: May 02 2025 at 03:31 UTC