Zulip Chat Archive

Stream: general

Topic: decidable instances in indicator lemmas


Floris van Doorn (May 12 2022 at 08:57):

I just saw #13834 by @Eric Wieser and I'm curious why we are doing this.
We rarely have [decidable (a ∈ s)], I guess the main examples are (co)finite sets on types with decidable equality.
The PR shows that this leads to quite some cases where you have to add an extra classical to the argument. And we've had some times-outs when checking decidable (but maybe that was only for decidable equality?)
In a few cases, you might actually be able to have a decidable instance, but there are many ways you can still solve your goal (congr, convert, simp, simp_rw, split_ifs, ...). Sure, it is confusing, but I think it will be confusing more often when you're missing a classical in your environment (and note that we're almost always rewriting from left-to-right with docs#set.indicator_apply, so there usually won't be any trouble unifying the LHS with your expression).

Similar remarks apply to #11708. I was helping @Ashvni Narayanan yesterday adopting the suggested comments, and it seems weird to me to consider whether decidable (a ∈ U) when U is a clopen set in a topological space. Sure, it might happen a couple of times, but it will not be relevant the vast majority of times. I thought we were moving away from such "constructive" considerations?

Eric Wieser (May 12 2022 at 09:39):

This was following what I've seen called "Yury's rule", which essentially states "never write a lemma that mentions a specific decidable instance when you could mention a generic one"

Anne Baanen (May 12 2022 at 09:57):

(That rule applies to any class living in Type, in particular fintype.)

Floris van Doorn (May 12 2022 at 10:07):

I agree that rule is generally good to follow.
Do we want to follow this rule this strictly?
In this case we rarely have a decidable instance and the decidable instance only occurs in the RHS of a lemma that you'll almost always use to rewrite left-to-right.
But maybe always following the rule is easier.
(cc @Yury G. Kudryashov)

Yury G. Kudryashov (May 12 2022 at 15:05):

In any case, I don't understand why do we need all these letI in #13834. What's wrong with open_locale classical? You can still add [decidable _] arguments when you need them.

Yury G. Kudryashov (May 12 2022 at 15:07):

E.g., rw [indicator] should work without classical.

Yury G. Kudryashov (May 12 2022 at 15:08):

Same question about the code using indicator: why not open_locale classical?

Eric Wieser (May 12 2022 at 17:05):

The danger with open_locale classical is that it encoruages you to forget to write your lemmas with the appropriate decidable assumptions

Eric Wieser (May 12 2022 at 17:05):

If I finished my linter for that then I guess it wouldn't matter

Gabriel Ebner (May 12 2022 at 17:59):

but there are many ways you can still solve your goal ([...] simp, simp_rw, [...])

I just want to point out that simp and simp_rw (in general) don't solve goals with different (non-canonical) decidable instances. Think for example about ite p 0 1 = ite p 0 1, simp won't solve this, and simp_rw [eq_self_iff_true] won't crack it either.

Eric Rodriguez (May 12 2022 at 18:00):

I thought this was the point of your new congr changes for simp recently?

Gabriel Ebner (May 12 2022 at 18:01):

Before the congruence lemma change, simp would introduce non-canonical decidable instances. (So it was impossible to avoid them.) But the change won't help if there are already non-canonical decidable instances in the input formula (or in the rhs of a simp lemma).

Floris van Doorn (May 12 2022 at 18:30):

Oh, good to know. Thanks for the correction!

Yury G. Kudryashov (May 12 2022 at 19:20):

Eric Wieser said:

The danger with open_locale classical is that it encoruages you to forget to write your lemmas with the appropriate decidable assumptions

AFAIR, @Mario Carneiro suggested the following trick:

  1. Disable open_locale classical.
  2. Add [decidable*] assumptions to all lemmas that have errors in their statements (not proofs).
  3. Restore open_locale classical.
  4. Fix any proofs, if needed.

Eric Wieser (May 12 2022 at 20:25):

Yes, that works as a way to fix things but doesn't really help prevent new mistakes being introduced

Sebastien Gouezel (May 12 2022 at 21:28):

Can we hack something so that begin ... end opens classical, so that it would be available in the proofs (at least tactic proofs) but not in statements? On second thought, it's probably way too hacky though.

Yaël Dillies (May 12 2022 at 21:42):

This is bad still, because classical in proofs can introduce bad decidable instances.

Eric Wieser (May 12 2022 at 21:46):

I think the problem with tactic#classical is it introduces the instance with too high a priority

Yaël Dillies (May 12 2022 at 21:46):

It already happened to me that I had to replace classical why haveI := classical.dec_eq α to avoid poisoning other types with conflicting decidability instances.

Yaël Dillies (May 12 2022 at 21:47):

Yeah everything would work better if classical and open_locale classical weren't synonyms for "Poison me now".

Eric Wieser (May 12 2022 at 21:47):

The former is "poison my proof", the latter is "poison my statement but make my proof easier"

Eric Wieser (May 12 2022 at 21:48):

We need something in between

Yaël Dillies (May 12 2022 at 21:48):

The second can also poison your proof.

Eric Wieser (May 12 2022 at 21:48):

Do you have a #mwe?

Eric Wieser (May 12 2022 at 21:52):

Regarding "the priority is too strong"; can docs#tactic.set_basic_attribute be used to locally enable an instance?

Eric Rodriguez (May 12 2022 at 22:07):

I've definitely found many proofs where I had to replace classicalwith letI := classical.dec_eq X

Eric Rodriguez (May 12 2022 at 22:07):

Also, this hack wouldn't work for lean4 as there's no begin/end

Eric Wieser (May 12 2022 at 22:32):

What does lean4 use as a marker to enter tactic mode?

Eric Wieser (May 12 2022 at 22:34):

I read the begin / end comment as "when in tactic mode", which should work just fine in lean 4

Eric Rodriguez (May 12 2022 at 22:36):

It's just by, iirc. I think a beginc/byc may be nice though.

Eric Wieser (May 12 2022 at 22:38):

I think if we can fix the bad behavior of docs#tactic.classical tactic this mostly becomes moot

Eric Rodriguez (May 12 2022 at 22:40):

I mean, golfing is always nice :)

Eric Rodriguez (May 12 2022 at 22:40):

more mathematician-mode is always good

Mario Carneiro (May 12 2022 at 23:20):

re: lean4, why isn't by classical; ... sufficient?

Reid Barton (May 13 2022 at 00:16):

How can a proof be poisoned?

Yaël Dillies (May 13 2022 at 00:17):

It can if you're constructing an object internal to the proof.

Eric Wieser (May 13 2022 at 12:55):

Eric Wieser said:

Regarding "the priority is too strong"; can docs#tactic.set_basic_attribute be used to locally enable an instance?

Let's see if this works: #14122

Eric Wieser (May 15 2022 at 09:43):

CI seems to pass locally, and this tidies up a handful of weird congrs in proofs

Eric Wieser (May 15 2022 at 10:03):

Interestingly a bunch of uses of classical really just meant resetI


Last updated: Dec 20 2023 at 11:08 UTC