Zulip Chat Archive

Stream: Is there code for X?

Topic: Reference a part of an expression


Patrick Johnson (Mar 17 2022 at 18:22):

After unfolding/simplifying expressions, sometimes I end up with a very large and complicated expression appearing in multiple assumptions and in the goal. What I usually do is generalize h : copy_pasted_large_expression = x and then rw h at h1 h2 h3 .... Is it possible to avoid copying and pasting? Can we somehow describe the location of the expression we want to reference? For example, given an assumption like this:

h : P (f (g x y) (g x y)) (Q (g x y))

I would like to be able to reference g x y by describing its location inside the type of assumption h (something like an expression path, taking left/right choices while descending the function application/lambda expressions). It is probably possible to write a tactic, but is there something like this already in Lean/mathlib?

Johan Commelin (Mar 17 2022 at 18:36):

I'm not aware of anything like that atm

Eric Wieser (Mar 17 2022 at 19:24):

Can you give a #mwe to play around with?

Eric Wieser (Mar 17 2022 at 19:28):

I guess it's

example {α β γ δ ε} (g : α  β  γ) (f : γ  γ  δ) (P : δ  ε  Prop) (Q : γ  ε) (x: α) (y : β)
  (h : P (f (g x y) (g x y)) (Q (g x y))) : true :=
begin

end

Kevin Buzzard (Mar 17 2022 at 19:28):

@Reid Barton IIRC you once wrote some cute trick to extract the LHS of an equation from the equation. Do you remember what I'm talking about?

Eric Wieser (Mar 17 2022 at 19:30):

Does this do what you want?

import tactic  -- doesn't show `:= g x y` without this!?

example {α β γ δ ε} (g : α  β  γ) (f : γ  γ  δ) (P : δ  ε  Prop) (Q : γ  ε) (x: α) (y : β)
  (h : P (f (g x y) (g x y)) (Q (g x y))) : true :=
begin
  let G_expr := _,
  have : P (f G_expr G_expr) (Q G_expr) := h,
  trivial
end

Eric Wieser (Mar 17 2022 at 19:30):

Here lean fills out the _ for you, which is presumably the bit you didn't want to copy-paste

Kyle Miller (Mar 17 2022 at 19:31):

You can use conv mode to locate a particular expression, then there could be a conv tactic (maybe generalize_goal?) that would do the rest?

Patrick Johnson (Mar 17 2022 at 20:20):

Here lean fills out the _ for you, which is presumably the bit you didn't want to copy-paste

I'm really surprised that it works.

Reid Barton (Mar 17 2022 at 23:01):

Kevin Buzzard said:

Reid Barton IIRC you once wrote some cute trick to extract the LHS of an equation from the equation. Do you remember what I'm talking about?

Yes vaguely but I don't know how to find it. It involved some similar let with _ as body trick.

Patrick Johnson (Mar 17 2022 at 23:31):

Maybe this?

Reid Barton (Mar 17 2022 at 23:44):

Oh that's not what I was thinking of, but also good! Maybe what Kevin was thinking of

Reid Barton (Mar 17 2022 at 23:45):

I'm thinking of something more like (probably essentially the same as) what Eric wrote

Joachim Breitner (Mar 18 2022 at 17:46):

I tried to take @Eric Wieser ’s suggestion and re-do it using conv like this:

example {α β γ δ ε} (g : α  β  γ) (f : γ  γ  δ) (P : δ  ε  Prop) (Q : γ  ε) (x: α) (y : β)
  (h : P (f (g x y) (g x y)) (Q (g x y))) : true :=
begin
  let G_expr := _,
  conv at h in (Q _) { congr, change G_expr, }

end

but unfortunately, I get (with set_option trace.app_builder true on)

[app_builder] failed to create an 'eq'-application, failed to solve unification constraint for #1 argument (γ =?= ?m_1)

It does work if I manually specify G_expr’s type; after

example {α β γ δ ε} (g : α  β  γ) (f : γ  γ  δ) (P : δ  ε  Prop) (Q : γ  ε) (x: α) (y : β)
  (h : P (f (g x y) (g x y)) (Q (g x y))) : true :=
begin
  let G_expr : γ := _,
  conv at h { congr, skip, congr, change G_expr, },

I get a goal state of

G_expr: γ := g x y
h: P (f (g x y) (g x y)) (Q G_expr)

Oh, and oddly, I cannot use

  conv at h in (Q _) { congr, change G_expr, },

or

  conv at h { find (Q _) { congr, change G_expr, }, },

– maybe find prevents the unification from escaping?

Joachim Breitner (Mar 18 2022 at 18:08):

Fun, because of this problem(?) of find hiding the side-effects from unification, I can prove false, or at least believe I am proving it, until the end of the lemma:

example : false :=
begin
  have h : id (tt  ff), simp,
  let b : bool := _,
  {
    conv at h in (id _) { congr, to_lhs, change b, skip, },
    conv at h in (id _) { congr, to_rhs, change b, skip, },
    have : b  b := h,
    show false, exact this rfl,
  },
  exact tt,
end

Is this worth fixing?

Kevin Buzzard (Mar 18 2022 at 18:10):

ha, yeah, you might be able to trick the tactic monad but you can't trick the kernel :-)

Kyle Miller (Mar 18 2022 at 18:52):

@Joachim Breitner That seems worth looking into to me. I'm not sure whether it's a bug or a known limitation that the metavariables for the let binding don't get instantiated (I think that's the word).

Eric Wieser (Mar 18 2022 at 23:25):

I remember there being some nasty state bugs last time I looked at the find tactic

Eric Wieser (Mar 18 2022 at 23:26):

Namely that if I tried to preserve the state properly in the lean code, the VM would crash


Last updated: Dec 20 2023 at 11:08 UTC