Zulip Chat Archive

Stream: mathlib4

Topic: Quotient.mk vs .mk' vs .mk''


Eric Wieser (Sep 17 2023 at 15:22):

We currently have three different ways to build an element of Quotient s. Not only is this one more than we had in Lean 3, but the new names are permuted with respect to the old names:

Setoid argument Lean 3 Lean 4
(s : setoid _) docs#Quotient.mk (core, ⟦a⟧)
{s : setoid _} docs3#quotient.mk' docs#Quotient.mk'' (mathlib)
[setoid _] docs3#quotient.mk (⟦a⟧) docs#Quotient.mk' (core)

Should we eliminate some of these?

Ruben Van de Velde (Sep 17 2023 at 15:28):

I started eliminating mk'' in a branch not so long ago, but got distracted

Ruben Van de Velde (Sep 17 2023 at 18:36):

Btw, the meaning of ⟦a⟧ also changed between 3 and 4

Eric Wieser (Sep 17 2023 at 18:39):

It's now Quotient.mk'' but used to be quotient.mk, right?

Kyle Miller (Sep 17 2023 at 18:40):

-- Porting note: in mathlib3 this notation took the Setoid as an instance-implicit argument,
-- now it's explicit but left as a metavariable.
-- We have not yet decided which one works best, since the setoid instance can't always be
-- reliably found but it can't always be inferred from the expected type either.
-- See also: https://leanprover.zulipchat.com/#narrow/stream/113489-new-members/topic/confusion.20between.20equivalence.20and.20instance.20setoid/near/360822354
@[inherit_doc]
notation:arg "⟦" a "⟧" => Quotient.mk _ a

Kyle Miller (Sep 17 2023 at 18:41):

I think the problem with Quotient.mk'' now is that Lean wants to resynthesize the Setoid instance from scratch, and it refuses to pick it up from the expected type.

Eric Wieser (Sep 17 2023 at 18:42):

Oh, so mk'' x : Quotient s doesn't work?

Kyle Miller (Sep 17 2023 at 18:42):

I don't believe so

Eric Wieser (Sep 17 2023 at 18:43):

I don't see why mk _ would be any different

Kyle Miller (Sep 17 2023 at 18:43):

Lean 4 resynthesizes instances, even for metavariables that have been solved for, and then checks that the value of the metavariable is defeq to the resynthesized instance.

Kyle Miller (Sep 17 2023 at 18:44):

With mk _, it's not an instance argument, so it won't try resynthesizing.

Eric Wieser (Sep 17 2023 at 18:44):

mk'' also isn't an instance argument

Eric Wieser (Sep 17 2023 at 18:45):

Ah sorry, I'm getting my primes confused

Eric Wieser (Sep 17 2023 at 18:45):

The table above was wrong, I've corrected it

Kyle Miller (Sep 17 2023 at 18:47):

Yeah, there's no difference in behavior between using Quotient.mk _ a and Quotient.mk'' a, except perhaps that Quotient.mk'' doesn't unfold to Quotient.mk

Eric Wieser (Sep 17 2023 at 18:47):

That seems like a very strong reason to eliminate one of mk and mk'' entirely

Ruben Van de Velde (Sep 17 2023 at 18:48):

https://github.com/leanprover-community/mathlib4/compare/quotient-mk?expand=1

Eric Wieser (Sep 17 2023 at 18:48):

You may as well use the notation there, right?

Kyle Miller (Sep 17 2023 at 19:00):

Something we've discussed before is making the notation be a notation typeclass. That would help keep Quotient from leaking, if every type that has a quotient could specify exactly how it wants the result type to be represented. Plus this would work for non-Quotient quotients (i.e., types that categorically are a quotient).

Eric Wieser (Sep 17 2023 at 19:01):

I'm confused about how that would be any different from Setoid being a typeclass, which it already is?

Kyle Miller (Sep 17 2023 at 19:02):

The second part, where you can choose a different type for the quotient than Quotient.

Eric Wieser (Sep 17 2023 at 19:02):

I don't think mathlib has any places where it wants to do that?

Kyle Miller (Sep 17 2023 at 19:03):

Aren't there at least a lot of abbreviations for Quotient?

Eric Wieser (Sep 17 2023 at 19:03):

I guess docs#RingQuot is the only example that comes to mind

Eric Wieser (Sep 17 2023 at 19:03):

But I was trying to eliminate that in favor of docs#RingCon anyway

Kyle Miller (Sep 17 2023 at 19:04):

Wherever you have an abbreviation for Quotient and you use the ⟦x⟧ notation, you get an API leak, since the notation naturally has type Quotient ... rather than your abbreviation.

Kyle Miller (Sep 17 2023 at 19:08):

One of the issues though is you want some bidirectional communication during elaboration -- an outParam isn't enough (and maybe not even ideal). Given ⟦x⟧ : Q you want to derive from Q an X to help elaborate x with expected type X.

(It's not completely clear that you want X to determine Q, since you might want to use the notation for the quotient into multiple quotient types, though perhaps if you're working with multiple quotient groups you'd want the subgroups you're quotienting by to be explicit in the notation.)

Eric Wieser (Sep 17 2023 at 19:11):

By "abbreviation", do you mean "def but not abbrev"?

Eric Wieser (Sep 17 2023 at 19:11):

Because if you're using abbrev then the "leak" is by design

Kyle Miller (Sep 17 2023 at 19:26):

I mean the difference between for example QuotientGroup.mk x : G ⧸ s and ⟦x⟧ : Quotient someSetoidInst

Kyle Miller (Sep 17 2023 at 19:27):

Even if (⟦x⟧ : G ⧸ s) elaborates, the type of this term is syntactically Quotient ...

Kyle Miller (Sep 17 2023 at 19:28):

Wouldn't it be better if ⟦x⟧ could have a type that's syntactically what we want in a given context? Seeing a Quotient type in the middle of a proof about groups seems very much like a leaked implementation detail to me.

Eric Wieser (Sep 17 2023 at 19:47):

Alternatively we could replace HasQuotient with a HasToSetoid class, and make R ⧸ S be notation for Quotient (HasSetoid.toSetoid S)

Newell Jensen (Oct 12 2023 at 19:58):

Was there ever a decision on this?


Last updated: Dec 20 2023 at 11:08 UTC