Zulip Chat Archive

Stream: mathlib4

Topic: Proofs that end with Exists.choose_spec


Robert Maxton (Apr 24 2025 at 06:22):

I seem to keep writing proofs relying on Exists.choose, whose final line turn out to be essentially Exists.choose_spec, except that the existential hypothesis has either been transformed into something ugly, or I've simply lost the original name. Currently, I handle this with

...
simp
generalize_proofs h
exact h.choose_spec

or the like; but this is of course a non-terminal simp. Is there a systematically better way to handle this I don't know about?

Robert Maxton (Apr 24 2025 at 06:23):

(The main issue here, I believe, is that there's no nice way to address the existential hypothesis; I've tried simpa using Exists.choose_spec _, for example, but unless it's simple enough that I can just fill in the name myself that doesn't seem to work.)

Robert Maxton (Apr 24 2025 at 06:24):

I could use generalize_proofs before the simp, but then I end up with many proofs I would have to separately combine, probably with another simp anyway.

Ruben Van de Velde (Apr 24 2025 at 06:41):

It surprises me that you end up in this situation. Would it not be easier to do obtain \<x, hx\> := h_exists rather than let x := Exists.choose h_exists?

Sébastien Gouëzel (Apr 24 2025 at 06:41):

Instead of using Exists.choose, can you use the choose tactic, which is much more user-friendly?

Robert Maxton (Apr 24 2025 at 06:42):

Ruben Van de Velde said:

It surprises me that you end up in this situation. Would it not be easier to do obtain \<x, hx\> := h_exists rather than let x := Exists.choose h_exists?

I usually don't do either, actually; I just have e.g. hom | ⟨x, hx⟩ => (hx (𝟙 _)).choose

Robert Maxton (Apr 24 2025 at 06:42):

Sébastien Gouëzel said:

Instead of using Exists.choose, can you use the choose tactic, which is much more user-friendly?

Hm. Let's find out.

Robert Maxton (Apr 24 2025 at 06:45):

Nope; or, well, certainly I can write hom | ⟨x, hx⟩ => by choose y hy using hx (𝟙 _); exact y instead, but when I then have to interact with that definition later simpa using (Classical.choose_spec _) doesn't work

Ruben Van de Velde (Apr 24 2025 at 06:46):

I see

Robert Maxton (Apr 24 2025 at 06:46):

... I suppose I should probably have been more specific: the issue is with defining data at one point in a definition with Exists.choose, where later I need to access that data with Exists.choose_spec

Robert Maxton (Apr 24 2025 at 06:47):

... I could use Classical.indefiniteDescription everywhere instead; that would be ugly but might be more compatible with automation...

Ruben Van de Velde (Apr 24 2025 at 06:47):

In that case it might be easier to create an auxiliary def with the result of Exists.choose and add a specialized lemma about that def with Exists.choose_spec

Ruben Van de Velde (Apr 24 2025 at 06:47):

I'm reasonably sure Classical.indefiniteDescription would be more painful

Robert Maxton (Apr 24 2025 at 06:49):

Well, it'd mean that the last line of my data generation is Subtype.val _, which sometimes simp seems to be able to exploit automatically via Subtype.coe_prop.

Robert Maxton (Apr 24 2025 at 06:49):

Ruben Van de Velde said:

In that case it might be easier to create an auxiliary def with the result of Exists.choose and add a specialized lemma about that def with Exists.choose_spec

Mm. That would be somewhat unpleasant as this is occurring in a rather deeply nested series of definitions, but that itself probably isn't great practice... I'll think about it.

Sébastien Gouëzel (Apr 24 2025 at 06:57):

Do you have a #mwe?

Yury G. Kudryashov (Apr 24 2025 at 14:32):

BTW, I think that we should have an attribute version of the choose tactic. It should take a lemma claiming \forall a b, \ex x, p x \and q x and output def with lemmas.

Yury G. Kudryashov (Apr 24 2025 at 14:32):

(both choose and choose! versions can be useful)

Kyle Miller (Apr 24 2025 at 15:26):

Maybe @[split] could in general destruct the target type and make new declarations, using some list of types that we'd normally split (curry) if they were arguments to a function or lemma. What come to mind: and, exists, sigma, subtype, maybe prod.

Ah, maybe the syntax is @[split ⟨thm1, ⟨thm2, thm3⟩, thm4⟩] and there does not need to be a list of "blessed" types. There would be an implicit intro for this destruct syntax, so for example the ⟨thm2, thm3⟩ could be parameterized by more arguments if it's a forall there.

Kyle Miller (Apr 24 2025 at 15:29):

(Somewhat related: the discussion about mutual induction. This link is to joint theorem definitions.)

Yury G. Kudryashov (Apr 24 2025 at 16:24):

Should it be a superset of alias?


Last updated: May 02 2025 at 03:31 UTC