Zulip Chat Archive

Stream: general

Topic: ZFC definable class


Violeta Hernández (Jul 10 2022 at 00:54):

Currently, docs#pSet.definable is implemented as a class. Should it be?

Violeta Hernández (Jul 10 2022 at 00:54):

My instinct says no, given what's been discussed here before: typeclasses are really only useful when there's no nontrivial equalities between objects, and sets/set functions completely break that rule

Violeta Hernández (Jul 10 2022 at 00:57):

On the other hand, we do have the theorem docs#classical.all_definable stating all functions are classically definable. So maybe this is meant to be used in a way more akin to decidable_eq or decidable_rel

Violeta Hernández (Jul 10 2022 at 01:03):

(i.e. as an afterthought :stuck_out_tongue:)

Violeta Hernández (Jul 10 2022 at 02:34):

Oh yeah, I should probably tag @Mario Carneiro who made this class to begin with

Mario Carneiro (Jul 10 2022 at 02:38):

The intention was to have definability instances for all formulas, but it was too much work at the time and classical.all_definable is an easy workaround using choice

Mario Carneiro (Jul 10 2022 at 02:39):

the rule for typeclasses is not about whether equalities exist but rather whether it is generally possible to prove all instances purely structurally on the value

Mario Carneiro (Jul 10 2022 at 02:41):

decidable is a good example of this - there are often nontrivial equalities of decidable instances but the important thing is that you prove that a thing is decidable because it is structurally so

Violeta Hernández (Jul 10 2022 at 02:42):

Well, in this situation, that should probably be the case

Mario Carneiro (Jul 10 2022 at 02:42):

There is a metatheorem that says that any ZFC formula is definable, but I don't think it is easy to derive this using only typeclass search because you have to combine many arities of definability

Violeta Hernández (Jul 10 2022 at 02:43):

Though wouldn't this also be the case for e.g. continuous functions? What was the rationale for not making that into a typeclass again? Feel like this was brought up last time I started a similar discussion

Mario Carneiro (Jul 10 2022 at 02:43):

The idea is that it shouldn't be necessary to invoke choice to use the axiom of replacement

Mario Carneiro (Jul 10 2022 at 02:44):

It does hit the same issues as continuous functions

Mario Carneiro (Jul 10 2022 at 02:44):

the full derivation setup was never done

Mario Carneiro (Jul 10 2022 at 02:44):

so it's basically a stub right now

Mario Carneiro (Jul 10 2022 at 02:44):

with the only way to prove definability being all_definable

Mario Carneiro (Jul 10 2022 at 02:45):

you can of course still do manual proofs for specific formulas, but a tactic would probably be best placed to do the full metatheorem

Violeta Hernández (Jul 10 2022 at 02:45):

I should mention that I just took care of your to-do: #15216

Violeta Hernández (Jul 10 2022 at 02:45):

But yeah, I agree that we need further development here

Violeta Hernández (Jul 10 2022 at 02:46):

Mario Carneiro said:

It does hit the same issues as continuous functions

What were those issues again?

Mario Carneiro (Jul 10 2022 at 02:51):

typeclass inference doesn't work well under lambdas

Mario Carneiro (Jul 10 2022 at 02:52):

you would like to reason that because + is continuous and f and g are continuous, \lam x, f x + g x is also continuous, and this is hard for the typeclass system to unify with the necessary instances

Mario Carneiro (Jul 10 2022 at 02:53):

If you write it in a first order way, like map2 (+) f g, then TC can do it

Mario Carneiro (Jul 10 2022 at 02:53):

but writing ZFC formulas like that would be pretty painful

Mario Carneiro (Jul 10 2022 at 02:54):

this is actually how computability/primrec "instances" are done right now, although it should get some automation at some point

Mario Carneiro (Jul 10 2022 at 02:54):

instances in quotes because they are worked out by hand

Mario Carneiro (Jul 10 2022 at 02:56):

you get stuff like list_cons.comp (hg.comp fst (fst.comp snd)) (snd.comp snd) where fst.comp snd and snd.comp snd are basically a way to write de bruijn variable references

Violeta Hernández (Jul 10 2022 at 02:58):

I see

Violeta Hernández (Jul 10 2022 at 02:58):

So the play here is to move away from instances and into metaprogramming

Violeta Hernández (Jul 10 2022 at 02:58):

Now would be a great time to actually learn about Lean metaprogramming

Violeta Hernández (Jul 10 2022 at 03:00):

What sorts of theorems would we want in the case of ZFC though?

Violeta Hernández (Jul 10 2022 at 03:01):

I can think of a few theorems for functions, like if f is definable, so is lambda x, {f x}, that kind of stuff

Violeta Hernández (Jul 10 2022 at 03:01):

But what about functions with more inputs?

Mario Carneiro (Jul 10 2022 at 03:25):

As far as theorems, we would want at least enough theorems so that manual proving would show the metatheorem

Mario Carneiro (Jul 10 2022 at 03:26):

So that means proving that all the primitives are definable, and forall and implies are definable

Mario Carneiro (Jul 10 2022 at 03:26):

this is difficult because you need some higher order notions of definability to make everything work out

Kevin Buzzard (Jul 10 2022 at 04:22):

@Violeta Hernández if you learn metaprogramming you can help with the Lean 4 port! I'm going to try and learn it next week!

Violeta Hernández (Jul 10 2022 at 17:56):

On a related note, now that I brought ZFC up

Violeta Hernández (Jul 10 2022 at 17:56):

docs#Class.mem_hom_left and docs#Class.mem_hom_right

Violeta Hernández (Jul 10 2022 at 17:57):

These seem like bad simp lemmas? For the same reason

example {α : Type*} {x : set α} {a : α} : a  x  x a := iff.rfl

would be a very bad simp lemma

Yaël Dillies (Jul 10 2022 at 17:58):

I am not so sure, because there indeed is something that decreases when going from the LHS to the RHS, namely the number of coercions.

Violeta Hernández (Jul 10 2022 at 17:59):

I mean, A x shouldn't be the preferred way to say x ∈ (A : set Set)

Violeta Hernández (Jul 10 2022 at 18:00):

(the RHS here isn't a coercion, since Class is def-eq to set Set)

Violeta Hernández (Jul 10 2022 at 18:02):

I see where this is coming from, since there's already another operator on Class

Violeta Hernández (Jul 10 2022 at 18:04):

But I'm still not a fan

Violeta Hernández (Jul 10 2022 at 19:10):

Is it not possible to have two different instances for a type?

Violeta Hernández (Jul 10 2022 at 19:10):

Having an instance has_mem Set Class and another has_mem Class Class would solve the problem at hand, but it doesn't seem to work

Violeta Hernández (Jul 10 2022 at 19:10):

Defining either instance makes the other no longer work

Violeta Hernández (Jul 10 2022 at 19:13):

I guess we could make an exception and say that A x is actually the proper way to say a set belongs to a class, even if this is blatant definitional equality abuse

Violeta Hernández (Jul 10 2022 at 19:20):

Here's an alternate idea, maybe we could have a predicate

def mem_set (x : Set.{u}) (A : Class.{u}) : Prop := A x

to hide the def-eq abuse

Violeta Hernández (Jul 10 2022 at 19:20):

Then change the theorems I mentioned to

@[simp] theorem Class.mem_hom_left (x : Set) (A : Class) : x  A  mem_set x A := sorry

Violeta Hernández (Jul 10 2022 at 19:21):

We could even go as far as to give custom notation like ∈ₛ for this, but that seems unnecessary

Violeta Hernández (Jul 11 2022 at 00:28):

I decided to go the mem_set route, and also added of_set for the cast between set Set and Class.

Violeta Hernández (Jul 11 2022 at 00:28):

#15234

Mario Carneiro (Jul 11 2022 at 02:10):

These are all technical definitions that are being used in the metamath export. I am against changing any of them

Mario Carneiro (Jul 11 2022 at 02:11):

Using application on Class is only abuse if we say it is

Violeta Hernández (Jul 11 2022 at 03:57):

Mario Carneiro said:

These are all technical definitions that are being used in the metamath export. I am against changing any of them

Metamath export? What do you mean?

Violeta Hernández (Jul 11 2022 at 04:00):

I get that we can do whatever we want with this little bit of code in a leaf file, but I still think it's best to be orderly. If we consider application on set α to be definitional abuse, then the situation surely shouldn't be any different with Class = set Set.

Violeta Hernández (Jul 11 2022 at 04:02):

It muddles the distinction between Class and Set → Prop (though maybe we don't want to make any such distinction? If so, we should instead document this decision and change Set → Prop to Class throughout).

Violeta Hernández (Jul 11 2022 at 04:06):

But yeah, I really want to know what that Metamath thing you mention is about. I don't think we should shy away from refactors just because the code is used by someone else.

Yury G. Kudryashov (Jul 11 2022 at 04:09):

How long does the metamath export you're talking about take? If it's fast, should we run it in the CI so that nobody breaks it by accident? Or could you add comments to definitions that should not be changed because of this export?

Violeta Hernández (Jul 11 2022 at 04:10):

Oh wait, are you running the entirety of Metamath on top of the mathlib ZFC library?

Violeta Hernández (Jul 11 2022 at 04:10):

That's both impressive and dreadful

Violeta Hernández (Jul 11 2022 at 04:11):

I really do think that Class is in an annoying state where its conventions aren't quite consistent (we use Class sometimes and Set → Prop other times and we mix and match with def-eq) and clash with those of mathlib elsewhere (the aforementioned def-eq abuse)

Violeta Hernández (Jul 11 2022 at 04:12):

But I guess I can live with it if it's needed for that Metamath thing to work, as long as we document things properly

Violeta Hernández (Jul 11 2022 at 04:17):

But also, would changing definitions to other definitionally equal definitions really break the Metamath export? That's all I'm ultimately suggesting

Eric Wieser (Jul 11 2022 at 07:28):

@Violeta Hernández, when threads like this spin out PRs, can you make sure to link back to the thread from the PR?

Violeta Hernández (Jul 11 2022 at 13:30):

Sorry, let me fix that

Mario Carneiro (Jul 11 2022 at 14:02):

Violeta Hernández said:

I get that we can do whatever we want with this little bit of code in a leaf file, but I still think it's best to be orderly. If we consider application on set α to be definitional abuse, then the situation surely shouldn't be any different with Class = set Set.

We could change the definition to Class = (Set -> Prop) to address this

Violeta Hernández (Jul 11 2022 at 14:18):

This wouldn't give us many instances automatically

Violeta Hernández (Jul 11 2022 at 14:18):

If the idea is that Class is morally Set → Prop, and we just define it as set Set to get the instances automatically, that's fine by me

Mario Carneiro (Jul 11 2022 at 14:22):

Violeta Hernández said:

But yeah, I really want to know what that Metamath thing you mention is about. I don't think we should shy away from refactors just because the code is used by someone else.

Well, mathlib is also used as a basis for other projects. I don't think it is necessary to gratuitously break downstream projects without good reason. (That is, set_theory.zfc only looks like a leaf file because it's not used in mathlib)

Violeta Hernández (Jul 11 2022 at 14:24):

I mean, mathlib changes so rapidly and Lean is so unpredictable in some aspects that I imagine that most refactors inadvertently break some mathlib dependencies

Violeta Hernández (Jul 11 2022 at 14:25):

But sure, we should have a good reason for these changes

Violeta Hernández (Jul 11 2022 at 14:25):

What do you think about replacing Set → Prop by Class, and explaining in a docstring that Class is morally Set → Prop?

Violeta Hernández (Jul 11 2022 at 14:25):

Would that break that Metamath thing?

Mario Carneiro (Jul 11 2022 at 14:26):

Yury G. Kudryashov said:

How long does the metamath export you're talking about take? If it's fast, should we run it in the CI so that nobody breaks it by accident? Or could you add comments to definitions that should not be changed because of this export?

It's somewhere in the 30 min range. I generally treat it as an external project which depends on mathlib, it has very few dependencies and they are all in the set_theory.zfc file

Mario Carneiro (Jul 11 2022 at 14:28):

Changing definitions without changing defeqs probably won't actually break things, since the export generates a lean source file with no tactics and lots of @ to avoid any lean weirdness so the only thing that would cause problems is typechecking failure due to changed definitions

Mario Carneiro (Jul 11 2022 at 14:28):

See https://leanprover.zulipchat.com/#narrow/stream/113488-general/topic/Prime.20number.20theorem.20in.20lean/near/168472336

Violeta Hernández (Jul 11 2022 at 14:31):

Another question

Violeta Hernández (Jul 11 2022 at 14:31):

Is docs#Class.to_Set another one of those definitions used in the Metamath export?

Violeta Hernández (Jul 11 2022 at 14:32):

If we were to replace Set → Prop by Class, then to_Set would just be a restatement of the predicate on classes

Violeta Hernández (Jul 11 2022 at 14:32):

(and by the way, I also want to inline Class.mem into the has_mem instance, would that break things?)

Violeta Hernández (Jul 11 2022 at 14:35):

Actually, more generally: what am I allowed to change, and would it be easy for me to fix the Metamath thing if anything broke?

Mario Carneiro (Jul 11 2022 at 14:36):

Another project that depends on ZFC is the independence of CH

Mario Carneiro (Jul 11 2022 at 14:39):

metamath will use Class.mem and Class.of_Set for sure but it may not use application

Mario Carneiro (Jul 11 2022 at 14:41):

as for going in and refactoring the export, you might be able to but you might need a different skill set to do it since part of it is written in haskell

Mario Carneiro (Jul 11 2022 at 14:42):

Most of the stuff that is likely to break is in basic.lean or post.lean

Violeta Hernández (Jul 11 2022 at 14:43):

Oh, it's good to have that reference

Alex J. Best (Jul 11 2022 at 14:44):

Maybe there is some small subset of the metamath export the that could be added to archive, at least to avoid breaking the whole thing.

Mario Carneiro (Jul 11 2022 at 14:44):

zfc_extra.lean is kind of a for_mathlib file

Violeta Hernández (Jul 11 2022 at 14:44):

I could port those theorems over if you want

Mario Carneiro (Jul 11 2022 at 14:44):

and as you can see most of this hasn't been touched since 2019

Mario Carneiro (Jul 11 2022 at 14:45):

but I tend to work in areas that don't break all that often so it probably still works

Violeta Hernández (Jul 11 2022 at 14:46):

Are these files generated automatically?

Mario Carneiro (Jul 11 2022 at 14:46):

no, the files I linked are all manual, the automatic stuff is not checked in

Mario Carneiro (Jul 11 2022 at 14:47):

well, most of basic.lean is based on an automatically generated file

Mario Carneiro (Jul 11 2022 at 14:47):

it's more sensitive to changes in set.mm than it is to changes in lean/mathlib

Violeta Hernández (Jul 11 2022 at 14:48):

Oh perfect

Violeta Hernández (Jul 11 2022 at 14:48):

I'll tread carefully to avoid breaking it, but I doubt I will with what I have in mind

Mario Carneiro (Jul 11 2022 at 14:49):

https://github.com/digama0/mm0/blob/build/mm0-lean/mm0/set/set.lean is one of the autogenerated files (it's broken into 6 parts)

Violeta Hernández (Jul 11 2022 at 14:55):

#15248

Violeta Hernández (Jul 13 2022 at 01:40):

What's up with the line just above docs#Set.mem_Union?

Violeta Hernández (Jul 13 2022 at 01:41):

That's global notation, right? Which I presume overrides the meaning of elsewhere

Violeta Hernández (Jul 13 2022 at 01:41):

If so, that's really silly, since that notation is only used once

Violeta Hernández (Jul 13 2022 at 01:42):

Regarding both this and the similar notation for Class, what should be done? Should these be localized, prefixed/suffixed with something else, or is there no point in having them?

Kyle Miller (Jul 13 2022 at 14:54):

Violeta Hernández said:

That's global notation, right? Which I presume overrides the meaning of elsewhere

Yes, it's global notation if you import it, but no it doesn't necessarily override the meaning of since Lean has a notation disambiguation system. However, this one seems problematic since it has a different sequence of parsing actions from those for set.Union. I believe this is why set.sUnion uses ⋃₀.

Kyle Miller (Jul 13 2022 at 14:55):

Violeta Hernández said:

If so, that's really silly, since that notation is only used once

Don't forget that just because something isn't used in mathlib doesn't mean it's not used by someone that uses mathlib as a dependency. This seems like something someone might want to use.

Violeta Hernández (Jul 13 2022 at 15:26):

Kyle Miller said:

However, this one seems problematic since it has a different sequence of parsing actions from those for set.Union. I believe this is why set.sUnion uses ⋃₀.

Should we suffix the notation for Set.Union too, then?

Kyle Miller (Jul 13 2022 at 16:13):

That seems reasonable to me. I don't know what @Mario Carneiro thinks (and I've never used the ZFC module myself), but I'd expect that the intent is that the ZFC API closely mirror the set API wherever possible.

Violeta Hernández (Jul 13 2022 at 19:00):

I don't have any good ideas for suffixes though...

Violeta Hernández (Jul 13 2022 at 19:00):

I wanted to be lazy and do a subscript Z for ZFC but that doesn't exist in Unicode

Kyle Miller (Jul 13 2022 at 19:38):

Oh, I thought when you said "should we suffix the notation" that we were talking about using ⋃₀, which should work.

Violeta Hernández (Jul 13 2022 at 21:29):

But that means we'll still have a clash

Violeta Hernández (Jul 13 2022 at 21:29):

Is clashing with ⋃₀ somehow better than clashing with ?

Junyan Xu (Jul 13 2022 at 21:55):

might consider using superscript ᶻ (reference)

Kyle Miller (Jul 13 2022 at 22:20):

@Violeta Hernández Yes, Lean should be able to disambiguate it better because it has the same "shape" vs . That's what I was referring to with parser actions.

Kyle Miller (Jul 13 2022 at 22:22):

Lean takes all possible parses and uses types to try to choose a single possibility. I don't think it works when one uses binders and the other doesn't, but I haven't checked yet.

Mario Carneiro (Jul 14 2022 at 03:09):

I think the notation should be ⋃₀ and the name should be sUnion for consistency with data.set.basic

Violeta Hernández (Jul 14 2022 at 03:16):

Kyle Miller said:

Violeta Hernández Yes, Lean should be able to disambiguate it better because it has the same "shape" vs . That's what I was referring to with parser actions.

I tested this and it doesn't seem to be the case. Lean Web Editor

Violeta Hernández (Jul 14 2022 at 03:16):

It tries using set.sUnion instead

Kyle Miller (Jul 14 2022 at 15:00):

@Violeta Hernández That example uses notation `⋃₀ ` instead of prefix `⋃₀ `:110, which would instead ensure the two unions have the same parsers. (See this.)

import set_theory.zfc

prefix `⋃₀ `:110 := Set.Union

def union (x y : Set) : Set := ⋃₀ {x, y}

Kyle Miller (Jul 14 2022 at 15:04):

One way to check this is that with the first version you have

notation `⋃₀ ` := Set.Union
#print notation ⋃₀
/-
`⋃₀`:110 := Set.Union
`⋃₀`:110 _:110 := set.sUnion #0
-/

but with the second you have

prefix `⋃₀ `:110 := Set.Union
#print notation ⋃₀
/-
`⋃₀`:110 _:110 :=
  | set.sUnion #0
  | Set.Union #0
-/

I believe that's what you need to see (options with |) for the disambiguation system to actually work.

Violeta Hernández (Jul 14 2022 at 15:11):

#15352


Last updated: Dec 20 2023 at 11:08 UTC