Zulip Chat Archive
Stream: general
Topic: Turning a datatype expression into a Prop
l1mey (Sep 07 2025 at 08:14):
Is there a way to turn an expression AST into a proposition, for example over the naturals? Here is some code below that it would look as:
inductive Inst : Type where
| const : (v : Nat) → Inst
| add : Inst → Inst → Inst
| sub : Inst → Inst → Inst
| hole : String → Inst
def lhs : Inst := .add (.hole "x") (.hole "y")
def rhs : Inst := .add (.hole "y") (.hole "x")
theorem equal : lhs.func = rhs.func :=
funext x y
...
Niels Voss (Sep 07 2025 at 09:21):
Sorry, I'm not quite sure what you're asking. Did you want help proving equal? Also, what is the definition of Inst.func?
l1mey (Sep 07 2025 at 20:13):
I'm wondering how I would write Inst.func, it would take in an Inst and create a function with an argument for every different hole and return that. Proving equal is just an example. Am I forced to use metaprogramming here?
Aaron Liu (Sep 07 2025 at 20:18):
can you give an example
Aaron Liu (Sep 07 2025 at 20:18):
what function will lhs.func be
l1mey (Sep 07 2025 at 20:20):
def lhs_func (x y : Nat) : Nat := x + y
Aaron Liu (Sep 07 2025 at 20:28):
how do you determine which strings correspond to which arguments
l1mey (Sep 07 2025 at 20:30):
Probably the first argument from the "left" which is x goes first. But that's an implementation detail. My question is if I am forced to use metaprogramming to construct such an expression and how would I do so.
Aaron Liu (Sep 07 2025 at 20:43):
it is possible to construct the function without metaprogramming
Aaron Liu (Sep 07 2025 at 20:44):
basically, define it recursively by pattern matching
Aaron Liu (Sep 07 2025 at 20:44):
you will probably have to use some sort of monad to keep track of which holes are which variables
Ilmārs Cīrulis (Sep 07 2025 at 20:48):
This doesn't work for you, right?
import Mathlib
inductive Inst : Type where
| const : (v : Nat) → Inst
| add : Inst → Inst → Inst
| sub : Inst → Inst → Inst
| hole : String → Inst
def meaning := String → Nat
def eval (M : meaning) (A : Inst) : Nat :=
match A with
| Inst.const v => v
| Inst.add X Y => eval M X + eval M Y
| Inst.sub X Y => eval M X - eval M Y
| Inst.hole s => M s
def equivalent (A B : Inst): Prop :=
forall (M : meaning), eval M A = eval M B
def lhs : Inst := .add (.hole "x") (.hole "y")
def rhs : Inst := .add (.hole "y") (.hole "x")
theorem identity : equivalent lhs rhs := by
unfold lhs rhs
intros M
simp [eval]
rw [add_comm]
I agree with Aaron Liu that it should be possible to construct what you want, of course.
Ilmārs Cīrulis (Sep 07 2025 at 20:50):
But I'm probably too slow to do it fast enough. :sweat_smile:
l1mey (Sep 07 2025 at 20:58):
After the simp [eval] it does give
M : meaning
⊢ M "x" + M "y" = M "y" + M "x"
This is okay for me, but it would be nicer to have a normal Lean expression.
Aaron Liu (Sep 07 2025 at 20:58):
this is a normal Lean expression???
Aaron Liu (Sep 07 2025 at 20:59):
what exactly are you looking for?
l1mey (Sep 07 2025 at 21:00):
def lhs.func (x y : Nat) : Nat := x + y
def rhs.func (x y : Nat) : Nat := y + x
which I'm guessing is only possible with metaprogramming.
Aaron Liu (Sep 07 2025 at 21:01):
it's possible without metaprogramming (but you won't be able to control the variable names)
Aaron Liu (Sep 07 2025 at 21:02):
it's just really, a weird thing to do?
Aaron Liu (Sep 07 2025 at 21:03):
by the way, I mean up to defeq of course
Aaron Liu (Sep 07 2025 at 21:03):
so you'll be able to do def lhs.func := Inst.func lhs and you'll be able to do theorem lhs.func_def : lhs.func = fun x y => x + y := rfl
Last updated: Dec 20 2025 at 21:32 UTC