Zulip Chat Archive
Stream: mathlib4
Topic: RFC: bundled sets #6442
Yury G. Kudryashov (Jan 13 2024 at 00:08):
In #6442, I started implementing #2202 for sets (not maps yet). Generic definitions are in Data/BundledSet/*
. I adjusted parts of docs#Subsemigroup to the new API, then stopped for now. Before I put more work into this, I would prefer to get some feedback about design choices.
Eric Wieser (Jan 13 2024 at 00:17):
I'm not yet convinced that things like
class BotPred (α : Type*) (p : Set α → Prop) (b : outParam (Set α)) : Prop where
bot : p b
bot_subset {t} : p t → b ⊆ t
are the right design, and am a bit worried about asking Lean to find a typeclass indexed by a function type. But I need to think about this more probably
Yury G. Kudryashov (Jan 13 2024 at 00:18):
Note that p
will be always something like IsSubsemigroup
or IsOpen
, not something you can unfold.
Eric Wieser (Jan 13 2024 at 00:19):
I do think that the part of your design that changes
structure Submonoid where
carrier : Set M
one_mem : 1 \mem carrier
to something analogous to
structure Submonoid where
carrier : Set M
isSubmonoid : IsSubmonoid carrier
is a good idea (in particularly, that design works much better with @Tomas Skrivan's fprop
-like tactics than what we have today)
Eric Wieser (Jan 13 2024 at 00:19):
I don't know if it's worth trying to go through this intermediate state first
Yury G. Kudryashov (Jan 13 2024 at 00:20):
There is an exception for instances designed to automatically prove SetInterPred
for algebraic subobjects but we can move them to a deriving
handler.
Yury G. Kudryashov (Jan 13 2024 at 00:28):
Do you suggest
structure Submonoid where
carrier : Set M
isSubmonoid : IsSubmonoid carrier
as you write above or
structure BundledSet (α : Type*) (p : Set α → Prop) where
carrier : Set α
prop : p carrier
@[to_additive (attr := reducible)]
def Submonoid (M : Type*) [OneMulClass M] := BundledSet M IsSubmonoid
as I use?
Yury G. Kudryashov (Jan 13 2024 at 00:29):
With my approach, you can prove generic theorems like mem_weaken
or weaken_weaken
that argue about different predicates.
Eric Wieser (Jan 13 2024 at 00:32):
I think your version is a more ambitious version of what I write above, and as such comes with more potential pitfalls to think about.
Yury G. Kudryashov (Jan 13 2024 at 00:33):
That's why I decided to take a pause and ask for feedback.
Eric Wieser (Jan 13 2024 at 00:37):
Note that for my suggestion above to work with dot notation, you actually need to write
import Mathlib
namespace Zulip
structure WithCarrier (α : Type _) where
carrier : Set α
structure IsSubmonoid {α : Type _} [Monoid α] (s : Set α) where
one_mem : 1 ∈ s
mul_mem {x y} : x ∈ s → y ∈ s → x * y ∈ s
-- `WithCarrier` is a hack to make `mul_mem` dot notation work;
-- we need the `IsSubmonoid ` to be seen as a parent structure,
-- not just a field; and so `carrier` needs to come before the extends
structure Submonoid (M : Type*) [Monoid M] extends WithCarrier M, IsSubmonoid carrier
variable (M : Type*) [Monoid M] (S : Submonoid M)
#check S.mul_mem -- works
Yury G. Kudryashov (Jan 13 2024 at 00:45):
My goal is to replace docs#SetLike with a single structure and docs#MulMemClass etc with [BundledSet.Implies _ _]
so that we can have generic theorems and don't search for SetLike
every time.
Eric Wieser (Jan 13 2024 at 00:47):
The main concern I have right now is that this doesn't work for things like SetLike Finset
(which admittedly I think we currently don't use); or in general, any set-like objects that carry extra computational data
Eric Wieser (Jan 13 2024 at 00:49):
But you should take my comments above as skepticism/hesitation, and not as an objection
Yury G. Kudryashov (Jan 13 2024 at 00:59):
I think that having common data for all algebraic subobjects is already a big improvement.
Yury G. Kudryashov (Jan 13 2024 at 01:03):
My goal is to have it for algebra and topology.
Yury G. Kudryashov (Jan 13 2024 at 01:03):
Indeed, Finset
won't fit this scheme.
Yury G. Kudryashov (Jan 13 2024 at 01:04):
This issue becomes more important for functions because we want to cover Equiv
s.
Yury G. Kudryashov (Jan 13 2024 at 01:05):
I'm OK with having a common structure for *Hom
and a different structure for Finsupp
but I want to have map_add
that works for Hom
s and Equiv
s.
Yury G. Kudryashov (Jan 13 2024 at 01:06):
Of course, this is what I am OK with. I will need to convince more people to push this change.
Yury G. Kudryashov (Jan 13 2024 at 01:43):
I think that this is a sufficiently large and important refactor to tag all @maintainers here.
Anne Baanen (Jan 13 2024 at 12:23):
I'm excited to see you take this forward! Finding a uniform representation is a good step towards taming the complexity of the current subobject setup.
Anne Baanen (Jan 13 2024 at 12:25):
Yury G. Kudryashov said:
so that we can have generic theorems and don't search for
SetLike
every time.
Is this really an issue in Lean 4? As far as I can tell, since there are very few classes extend
ing SetLike (I believe the actual number is 0) and everything is handled with "unbundled inheritance", keyed matching will reject most instances almost directly. That is the main motivation for #8386.
Anne Baanen (Jan 13 2024 at 12:33):
Eric Wieser said:
The main concern I have right now is that this doesn't work for things like
SetLike Finset
(which admittedly I think we currently don't use); or in general, any set-like objects that carry extra computational data
This could be fixed by relaxing the predicate from Set α → Prop
to Set α → Sort*
. Although I suppose we'd lose the properties deriving from SetLike.coe_injective
. So maybe it should look like:
structure BundledSet (α : Type*) (p : Set α → Sort*) [∀ x, Subsingleton (p x)] where
carrier : Set α
prop : p carrier
(I can't say if the typeclass system would work well with the ∀, or whether we should have an EverywhereSubsingleton p := ∀ x, Subsingleton (p x)
class instead, like docs#DecidablePred corresponds to docs#Decidable.)
Eric Wieser (Jan 13 2024 at 12:36):
I'm also somewhat worried about the consequence of losing the Submonoid
/ Subring
etc namespaces to put declarations under; it's great when we can unify a bunch of things as a single declaration under BundledSet
, but things will become messy when we can't
Yury G. Kudryashov (Jan 13 2024 at 15:33):
We can still have Submonoid
/Subring
namespaces.
Yury G. Kudryashov (Jan 13 2024 at 16:20):
DecidablePred
is reducible, so it doesn't matter.
Yury G. Kudryashov (Jan 14 2024 at 23:20):
So, is there any conclusion?
Yaël Dillies (Jan 15 2024 at 20:20):
I just came up with an interesting remark: docs#Subgroup won't be eligible for your BundledSet
approach once we have refactored it to work over monoids
Yaël Dillies (Jan 15 2024 at 20:24):
Currently, the definition is
structure Subgroup (G : Type*) [Group G] extends Submonoid G where
inv_mem' {x} : x ∈ carrier → x⁻¹ ∈ carrier
which is one data field (carrier : Set G
) and many Prop fields (which for BundledSet
purposes would be merged into a single prop : IsSubgroup carrier
field). If we want to generalize subgroups to monoids in a defeq-sensible way, we need something along the lines of
structure Subgroup (G : Type*) [Monoid G] extends Submonoid G where
inv : carrier → carrier
mul_left_inv (a) : (inv a : G) * a = 1
Yaël Dillies (Jan 15 2024 at 20:27):
Since most bundled sets in algebra build on Subgroup
, your BundledSet
approach (as currently proposed, at least) would apply to barely anything. And in turn merging your current BundledSet
approach would make refactoring Subgroup
much harder later. I think this is a pretty serious concern.
Yaël Dillies (Jan 15 2024 at 20:30):
I am mentioning Subgroup
here, but the same argument applies to subobjects of any structure that has Type-valued fields which can be uniquely determined by the other ones (I offer we call these "propositionally redundant fields"), eg docs#Sublattice, whose two data fields can be recovered from ≤
alone.
Jireh Loreaux (Jan 15 2024 at 20:32):
Do we have intentions to refactor Subgroup
to be apply to Monoid
s?
Yury G. Kudryashov (Jan 15 2024 at 20:35):
Current docs#Sublattice doesn't have any extra data fields.
Yury G. Kudryashov (Jan 15 2024 at 20:35):
BTW, the Subsingleton
approach mentioned above covers this.
Yury G. Kudryashov (Jan 15 2024 at 20:35):
Though we won't have nice SetInterPred
etc.
Yaël Dillies (Jan 15 2024 at 20:36):
Jireh Loreaux said:
Do we have intentions to refactor
Subgroup
to be apply toMonoid
s?
This has been discussed before, see https://leanprover.zulipchat.com/#narrow/stream/116395-maths/topic/Multiplicative.20subgroups.20of.20a.20ring
Yury G. Kudryashov (Jan 15 2024 at 20:36):
Do we really care about definitional equalities?
Yaël Dillies (Jan 15 2024 at 20:37):
Yury G. Kudryashov said:
Current docs#Sublattice doesn't have any extra data fields.
No my point is that it technically makes sense to talk about sublattices of a preorder (well, maybe partial order to ensure unicity).
Yaël Dillies (Jan 15 2024 at 20:37):
Yury G. Kudryashov said:
Do we really care about definitional equalities?
I would think for cases like docs#circle we do, at least remotely.
Yury G. Kudryashov (Jan 15 2024 at 20:38):
What's wrong with having Inv.inv
defined using Classical.choice
on a Subgroup
? Do we (plan to) have dependent types that need this definitional equality?
Eric Wieser (Jan 15 2024 at 22:24):
That sounds pretty annoying to me; I don't want the additive subgroup of ℕ × ℤ
for .fst = 0
to have non-computable negation
Yury G. Kudryashov (Jan 15 2024 at 22:35):
Note that basic operations like docs#Sup.sup will lead to noncomputable inverse for subgroups of monoids.
Yury G. Kudryashov (Jan 30 2024 at 16:49):
So, is there any conclusion about bundled sets?
Yury G. Kudryashov (Jan 31 2024 at 09:16):
Let me cross-link an alternative proposal: https://leanprover.zulipchat.com/#narrow/stream/287929-mathlib4/topic/Bundled.20sets.2Ffunctions.20with.20even.20more.20classes
Anne Baanen (Feb 13 2024 at 16:35):
Anne Baanen said:
Eric Wieser said:
The main concern I have right now is that this doesn't work for things like
SetLike Finset
(which admittedly I think we currently don't use); or in general, any set-like objects that carry extra computational dataThis could be fixed by relaxing the predicate from
Set α → Prop
toSet α → Sort*
. Although I suppose we'd lose the properties deriving fromSetLike.coe_injective
. So maybe it should look like:structure BundledSet (α : Type*) (p : Set α → Sort*) [∀ x, Subsingleton (p x)] where carrier : Set α prop : p carrier
(I can't say if the typeclass system would work well with the ∀, or whether we should have an
EverywhereSubsingleton p := ∀ x, Subsingleton (p x)
class instead, like docs#DecidablePred corresponds to docs#Decidable.)
This change seems indeed to work well:
universe u v
structure BundledSet (α : Type u) (p : Set α → Sort v) [∀ x, Subsingleton (p x)] :
Type (max u v) where
carrier : Set α
protected prop : p carrier
Anne Baanen (Feb 13 2024 at 17:02):
Some experiments later and it looks like Finset
can be practically implemented with the Sort
-valued BundledSet
as well.
Anne Baanen (Feb 13 2024 at 17:22):
This seems like a very big proposal, so IMO we should cut it into separate steps to see which ones are worth it.
- What I'll call the first step: I see no reason that replacing
structure Submonoid
with@[reducible] def Submonoid := BundledSet IsSubmonoid
won't work. This would essentially reintegrate the deprecated unbundled subobjects into the main hierarchy. On the other hand, we shouldn't expect too many gains from this switch, and it will be quite disruptive (although we'd be able to switch over each definition one by one). Perhaps automation/tactics are helped by the uniformity ofBundledSet
. - Simultaneously we could redefine
MulMemClass M S
as∀ (s : S), IsMulMem M s
. I expect that this brings some deduplication but otherwise is not too exciting. - Then we can define new classes such as
Implies
to make generic operators such as the empty set and intersection. This seems like an obvious advantage in expressivity, so if it works correctly (which I believe it likely will), this would make the previous step pay off. - The next step is to use the
Implies
class to automate generic declarations, instead of the current variety of___MemClass
es. I don't see why "so that we can have generic theorems and don't search forSetLike
every time" is a convincing argument for this: the discrimination tree matching makes this very fast (just like #8386 did forFunLike
). If anything, it seems like the search will be more expensive sinceImplies IsMulMem _ _ =?= Implies IsOneMem _ _
is slower to fail than not consideringIsOneMem
at all.
Anne Baanen (Feb 13 2024 at 17:24):
So in conclusion: I am cautiously optimistic that going ahead with the first three steps will prove to be worth it. I am not convinced about the last one, but I'd like very much to be proven wrong!
Yury G. Kudryashov (Feb 13 2024 at 18:34):
We can use generic Implies
only for forgetful functors.
Timo Carlin-Burns (Mar 21 2024 at 22:42):
Anne Baanen said:
This could be fixed by relaxing the predicate from
Set α → Prop
toSet α → Sort*
. Although I suppose we'd lose the properties deriving fromSetLike.coe_injective
. So maybe it should look like:structure BundledSet (α : Type*) (p : Set α → Sort*) [∀ x, Subsingleton (p x)] where carrier : Set α prop : p carrier
I wonder if that typeclass parameter would cause performance issues since it would mean that inferInstance : ∀ x, Subsingleton (p x)
appears in the definitions of so many abbrev
s, e.g. abbrev Submonoid M [Monoid M] := @BundledSet M IsSubmonoid inferInstance
.
Would any of these alternatives be an improvement?
- Using
Trunc
:
structure BundledSet (α : Type u) (p : Set α → Sort v) :
Type (max u v) where
carrier : Set α
prop' : Trunc (p carrier)
variable {α : Type u} {p : Set α → Sort v} [∀ s, Subsingleton (p s)]
def BundledSet.prop (s : BundledSet α p) : p s.carrier :=
Trunc.recOnSubsingleton (C := fun _ ↦ p s.carrier) s.prop' id
- Using a
Subsingleton
field:
structure BundledSet (α : Type u) (p : Set α → Sort v) :
Type (max u v) where
carrier : Set α
prop : p carrier
[subsingleton : Subsingleton (p carrier)]
- Adding the
[∀ s, Subsingleton (p s)]
hypothesis only when you need the coercion toSet α
to be injective.
Antoine Chambert-Loir (Mar 21 2024 at 23:28):
I was up to asking why not having bundled functions, as well as bundled sets, and I'd probably ask the question in the other direction—Why not copying for set the funlike classes? (So there would be SubmonoidClass, SubgroupClass, SubmoduleClass, etc.)
Yury G. Kudryashov (Mar 21 2024 at 23:29):
We have docs#MulMemClass
Yury G. Kudryashov (Mar 21 2024 at 23:30):
I think about ways to reduce code duplications without loss of generality/speed.
Yury G. Kudryashov (Mar 21 2024 at 23:30):
Also, it would be nice to have polymorphic lemmas like map_map
for any compatible FunLike
s and SetLike
s.
Antoine Chambert-Loir (Mar 21 2024 at 23:55):
What do people do in other proof assistants?
Mario Carneiro (Mar 22 2024 at 00:03):
this seems like a bit of a lean-specific problem, so it's difficult to compare with other systems
Yury G. Kudryashov (Apr 21 2024 at 07:26):
Let me come back to this and https://leanprover.zulipchat.com/#narrow/stream/287929-mathlib4/topic/Bundled.20sets.2Ffunctions.20with.20even.20more.20classes
What issues I want to be solved
- code duplication between various
SetLike
andDFunLike
objects; - unpredictable holes in API;
- inconsistent names;
- no way to talk about a type which is an
AddMonoidHomClass
with pointwise addition; the actual example I want to have is "an outer measure-like type with pointwise bottom and order"
Possible approaches
Uniform structures with generic instances
... as described above and in #2202
The main disadvantage of this approach is that in some cases, a bundled homomorphism/bundled set may need to use different order or multiplication.
E.g., 1
can be the bundled version of "cons _ 1 or
id`, but there are more examples, see https://leanprover.zulipchat.com/#narrow/stream/287929-mathlib4/topic/Order.20on.20measures for examples about order
While this is the approach I originally suggested, I see no way to accomodate for these special cases.
[PointwiseAdd] etc classes
Suggested by @Moritz Doll in https://leanprover.zulipchat.com/#narrow/stream/287929-mathlib4/topic/Bundled.20sets.2Ffunctions.20with.20even.20more.20classes
Instead of imposing any restrictions on the types, we define typeclasses saying that various operations (order, algebraic operations, inf/sInf for bundled sets) agree with pointwise operations.
I see two disadvantages compared to status quo:
-
Generic lemmas are never
dsimp
, even if they aredsimp
for 95% of the actual types.
Thus, if we care aboutdsimp
lemmas, then we need to formulate them for all types anyway; -
If we add generic instances like
[FunLike F α M] [Monoid M] [Mul F] [One F] [SMul Nat F] [PointwiseOne F] [PointwiseMul F] [PointwiseSMul Nat F] : Monoid F
, then we may get huge instance terms, especially once we start talking about types like(E →L[K] F) →L[K] (F →L[K] G) →L[K] (E →L[K] G)
. I have no data here.
Meta programming
We can have a meta program that specializes some generic theory to each bundled hom/set type. Maybe we can even build some kind of "hierarchy builder" that takes a file with all morphisms we care about and declares the corresponding types, theorems, and projections.
The main advantage of this approach is that we can get consistent naming and we can have autogenerated dsimp
lemmas.
The main disadvantages I see:
- This approach requires a lot of careful meta-programming, so fewer people can implement it and fewer people will understand how it works.
- We still don't get a way to generalize docs#MeasureTheory.Measure.ae to outer measures and have lemmas like
ae_mono
without code duplication.
Yury G. Kudryashov (Apr 21 2024 at 14:34):
@Anne Baanen @Moritz Doll What do you think?
@Yaël Dillies You may be interested since you're working on dropping some generic instances
@Mario Carneiro Are my concerns about blowup of the size of instances seem valid? If yes, any ideas how to avoid it?
Johan Commelin (Apr 22 2024 at 09:35):
I think it would be interesting to investigate the third approach in more detail. And maybe we should even see if we can use actual Hierarchy Builder to help with this job.
Antoine Chambert-Loir (Apr 23 2024 at 20:16):
Does @Cyril Cohen have some opinion about this question?
Yury G. Kudryashov (Apr 23 2024 at 20:18):
@Johan Commelin How would you formulate a lemma about any OuterMeasure
-like bundled map with pointwise order/addition/... (depending on a lemma)?
Yury G. Kudryashov (Apr 23 2024 at 20:19):
Assuming that meta code can build us a hierarchy with basic stuff.
Johan Commelin (Apr 24 2024 at 02:52):
Ooh, I don't claim that I can address any of the disadvantages you point out in any of your suggested approaches.
Yury G. Kudryashov (Apr 24 2024 at 02:53):
Of course, we can create "generic" instances + autodeclare all relevant instances for each specific class to speed up search.
Last updated: May 02 2025 at 03:31 UTC