Zulip Chat Archive

Stream: general

Topic: sufficesI


Yaël Dillies (May 08 2022 at 19:19):

Could we have an "instance version" of tactic#suffices? This would complete the have, haveI, suffices square.

Reid Barton (May 08 2022 at 19:21):

Do you have a practical use in mind for it?

Yaël Dillies (May 08 2022 at 19:22):

It has the same applications as haveI. For example I have this proof

  haveI : is_empty {a // b a = k},
  { refine subtype.is_empty_of_false _,
    rintro a rfl,
    exact hbk (finset.mem_image_of_mem _ $ finset.mem_univ _) },
  exact det_is_empty,

This would read slightly better as

  sufficesI : is_empty {a // b a = k},
  { exact det_is_empty },
  refine subtype.is_empty_of_false _,
  rintro a rfl,
  exact hbk (finset.mem_image_of_mem _ $ finset.mem_univ _),

Reid Barton (May 08 2022 at 19:31):

Ideally is_empty would not be a class in the first place, and you could just write apply det_is_empty and then the rest.

Yaël Dillies (May 08 2022 at 19:32):

Sure, but

  1. It should be a class
  2. My specific problem has little to do with the tactic gap that I just uncovered

Reid Barton (May 08 2022 at 19:35):

But I think this is really a representative example--my biggest problem with type class abuse is precisely that it makes these kinds of proofs more awkward. In the best case you make I duplicates of a bunch of tactics but it's still worse than just proving stuff normally; here you had to spell out the exact is_empty statement you need.

Reid Barton (May 08 2022 at 19:36):

I think what would make the situation more tolerable is something like an apply tactic that turns failed instance searches into new goals

Yaël Dillies (May 08 2022 at 19:37):

We should either have both haveI and sufficesI or none of them, because they fulfill the exact same role. Is your solution to delete haveI?

Reid Barton (May 08 2022 at 19:38):

??

Yaël Dillies (May 08 2022 at 19:38):

There's a mismatch between have and suffices. This mismatch shouldn't exist. What is your solution to it?

Reid Barton (May 08 2022 at 19:39):

Why do I need a solution?

Reid Barton (May 08 2022 at 19:39):

I think adding sufficesI is okay; but it doesn't address the real issue

Yaël Dillies (May 08 2022 at 19:40):

Sure, we can also add applyI which does what you say. I think this would be ideal.

Adam Topaz (May 08 2022 at 19:40):

We have apply_with

Adam Topaz (May 08 2022 at 19:40):

And you can just use suffices : foo, { resetI, bar }.

Yaël Dillies (May 08 2022 at 19:41):

How does one use apply_with?

Adam Topaz (May 08 2022 at 19:42):

apply_with ... { instances := ff }

Reid Barton (May 08 2022 at 19:45):

Does that mean all instance arguments will become new goals? That's probably not ideal either

Adam Topaz (May 08 2022 at 19:48):

Yeah, that's what it does. When I do it I usually have to do any_goal { apply_instance } right after

Damiano Testa (May 08 2022 at 20:33):

It might be that adding a tactic.swap at the end of the haveI tactic would generate the sufficesI tactic.
I'm not at a computer, so cannot check now, though.

Kyle Miller (May 08 2022 at 20:54):

You could use tactic#exactI here:

  suffices : is_empty {a // b a = k},
  { exactI det_is_empty },
  refine subtype.is_empty_of_false _,
  rintro a rfl,
  exact hbk (finset.mem_image_of_mem _ $ finset.mem_univ _),

Or there's

  suffices : is_empty {a // b a = k},
  unfreezingI { exact det_is_empty },
  refine subtype.is_empty_of_false _,
  rintro a rfl,
  exact hbk (finset.mem_image_of_mem _ $ finset.mem_univ _),

but tactic#unfreezingI doesn't focus the goal.

Kyle Miller (May 08 2022 at 20:58):

For longer proofs inside the first suffices goal, you can put tactic#resetI at the beginning. I think the value-add of haveI is that you don't have to do have : foo, { ...}, resetI, ... with the resetI potentially far away from the have.


Last updated: Dec 20 2023 at 11:08 UTC