Zulip Chat Archive

Stream: general

Topic: Closing `⊢` goals in `conv` mode


Eric Wieser (Oct 03 2020 at 17:27):

After running rw in conv mode with docs#finsupp.sum_map_domain_index (which requires two assumptions), I end up with one | goal and two goals.

I already know how to handle the | goal, and can discard it with skip. I'm then left with two goals, but:

  • I'm still in conv mode, so don't have any tactics to help me
  • If I leave conv mode, the | goal does not take effect

Is there a way to drop back into tactic mode in conv mode?

Johan Commelin (Oct 03 2020 at 17:28):

Good question! Does conv mode have an exact tactic?

Eric Wieser (Oct 03 2020 at 17:29):

No!

Johan Commelin (Oct 03 2020 at 17:29):

If not, I guess it should get it for situations like these.

Eric Wieser (Oct 03 2020 at 17:29):

But indeed, then I could use exact by { } which would hopefully do the trick

Eric Wieser (Oct 03 2020 at 17:30):

Furthermore, if I attempt a term-mode proof as an argument to sum_map_domain_index, if I get it wrong the error is silenced and the conv does nothing

Eric Wieser (Oct 03 2020 at 17:30):

almost- #mwe (needs some variables from monoid_algebra.lean):

-- in master shortly
def to_add_equiv : multiplicative G  G := multiplicative.to_add, multiplicative.of_add, of_add_to_add, to_add_of_add

def add_monoid_algebra.to_multiplicative :
  add_monoid_algebra k G ≃+* monoid_algebra k (multiplicative G) :=
{ map_mul' := λ x y, by {
    unfold finsupp.dom_congr to_add_equiv,
    simp [mul_def],
    simp_rw map_domain_sum,
    simp_rw map_domain_single,
    conv_rhs {
      for (finsupp.sum _ _) [1, 2] {
        rw finsupp.sum_map_domain_index,
        skip,
      },
    },
    sorry },
  map_add' := λ x y, by {
    simp [finsupp.dom_congr, map_domain_add],
  },
  ..finsupp.dom_congr to_add_equiv }

Eric Wieser (Oct 03 2020 at 18:48):

meta def conv.interactive.exact (q : interactive.parse interactive.types.texpr) : conv unit := tactic.interactive.exact q

seems to do the job, although I wonder if it warrants some special casing to only allow its use on goals

Eric Wieser (Oct 03 2020 at 18:49):

In fact even this works:

meta def conv.interactive.exact := tactic.interactive.exact

Eric Wieser (Oct 05 2020 at 14:57):

Should I PR the above?

Or should we change conv so that unsolved goals remain outside of the conv block?

Eric Wieser (Oct 05 2020 at 14:58):

And If I did use the above definition of exact, is there anything to stop the user closing a | goal with it nonsensically?

Eric Wieser (Oct 08 2020 at 12:12):

Here's a contrived #mwe showing when exact can be needed in conv mode:

import algebra.ring

meta def conv.interactive.tactic_exact := tactic.interactive.exact

variables {α : Type*} [ring α] {a b c : α}

lemma obvious : c = 1  (a * b) * c = a * b := λ h, by {rw [h, mul_one]}

example (hc : c = 1) (hb : b = 1) : (a * b) * c = a := begin
  conv_lhs {
    rw obvious,
    skip,
    -- goal is `| c`, which is nonsense
    tactic_exact by {
      -- goal is `⊢ c = 1`
      assumption,
    }
  },
  rw [hb, mul_one],
end

It seems that conv gets confused about the goal state after the rw.

Gabriel Ebner (Oct 08 2020 at 12:40):

In this case you could also use rw hc, skip instead of the tactic_exact.

Gabriel Ebner (Oct 08 2020 at 12:41):

conv doesn't really get confused here. Remember that conv is just a light wrapper around the standard tactic state that prints subgoals a = b as | a, and where the tactics operate on the left-hand side (a) of the equation.

Eric Wieser (Oct 08 2020 at 12:43):

Right, hence this example being contrived. The one earlier in this thread I can't work out any way to solve without tactic_exact.

Eric Wieser (Oct 08 2020 at 12:44):

I was not aware that was how conv works

Eric Wieser (Oct 08 2020 at 12:44):

But I feel like new goals introduced by rw should never be treated as | goals

Eric Wieser (Oct 08 2020 at 13:52):

Gabriel Ebner said:

that prints subgoals a = b as | a

Where does this actually happen? tactic.interactive_expr has some code to print ⊢ g as HTML, but I can't see where the rules for printing conv mode are.

Gabriel Ebner (Oct 08 2020 at 14:19):

It's implemented in conv.save_info (by passing a boolean flag to the C++ code..). This is a magic name. When Lean sees begin[conv] ... end, it looks for conv.save_info, conv.istep, etc.

Eric Wieser (Oct 08 2020 at 14:35):

I've never seen the syntax begin[...] before

Bryan Gin-ge Chen (Oct 08 2020 at 14:36):

It's not documented anywhere but that's how you enter a custom tactic mode.

Bryan Gin-ge Chen (Oct 08 2020 at 14:38):

There was some discussion on custom tactic modes in this thread.

Eric Wieser (Oct 08 2020 at 14:39):

Does that mean I can use begin[tactic] to switch back to tactic mode from conv mode?

Eric Wieser (Oct 08 2020 at 14:39):

Oh, I guess I need to be in an expression context

Eric Wieser (Oct 08 2020 at 14:42):

Gabriel Ebner said:

It's implemented in conv.save_info (by passing a boolean flag to the C++ code..). This is a magic name. When Lean sees begin[conv] ... end, it looks for conv.save_info, conv.istep, etc.

I don't see where that boolean flag is, conv.save_info looks like it just calls regular tactic code.

Gabriel Ebner (Oct 08 2020 at 14:44):

The boolean flag is in tactic_state.to_format.

Gabriel Ebner (Oct 08 2020 at 14:44):

I thought this works:

begin  begin[smt]  end end

Maybe this works as well?

by conv { begin[tactic] end }

Kevin Buzzard (Oct 08 2020 at 14:47):

@Eric Wieser the natural number game uses this begin [natnumgame] trick and that's how I stopped rw from closing refl goals

Eric Wieser (Oct 08 2020 at 14:56):

save_info is run automatically between conv tactics I assume?

Eric Wieser (Oct 08 2020 at 14:56):

I think what I'd like to happen, is that after rw runs, any new goals are marked with some kind of "not conv" flag

Eric Wieser (Oct 08 2020 at 14:57):

Which both:

  • Adjusts tactic state rendering
  • Allows exact to be used to close those goals (and those goals only)

Eric Wieser (Oct 08 2020 at 14:59):

But perhaps the simpler alternative is to make rw in conv mode take an extra argument, a tactic block

Eric Wieser (Oct 08 2020 at 14:59):

And have it use that tactic block to close any goals it creates.

Eric Wieser (Oct 08 2020 at 15:27):

Alright, I almost have this - but I'm stuck writing the tactic parser - I can't work out how to combine parse (tk ...) with itactic:

meta def rw2 (q : parse rw_rules) (cfg : rewrite_cfg := {}) (p : parse (tk "with" *> itactic)) : conv unit

fails with a type error, and I can't find any examples to follow

Eric Wieser (Oct 08 2020 at 15:50):

I've pushed the parts I can do to https://github.com/leanprover-community/lean/pull/475 - I'd appreciate help ironing out the details


Last updated: Dec 20 2023 at 11:08 UTC