Zulip Chat Archive
Stream: lean4
Topic: Private class/structure members
Andy Soffer (May 12 2024 at 22:15):
Lean has a really useful property where members with the same name are "coalesced" when inheriting as a mechanism to resolve the diamond-inheritance problem. One negative side-effect of this is that the coalescing happens by default, even if I don't want it to. I can of course give complex names to fields in the hopes that no one else uses that name, but I'm wondering if there is another mechanism to ensure that names aren't merged.
One could imagine, for example, having Monoid and Group classes each with an op
field, and wanting them to be coalesced in some cases, but not for Ring where the Monoid is for multiplication and the group is the additive group.
A. (May 12 2024 at 23:43):
I think if you avoid extends
then it doesn't happen? But I'm not sure and I seem to recall that I've been surprised before.
namespace pig1
class Monoid (α : Type) where op : α → α → α
class Group (α : Type) where op : α → α → α
class Ring (α : Type) extends Monoid α, Group α
example {α : Type} [Ring α] : (Ring.toMonoid.op : α → α → α) = Ring.toGroup.op :=
rfl -- succeeds
end pig1
namespace pig2
class Monoid (α : Type) where op : α → α → α
class Group (α : Type) where op : α → α → α
class Ring (α : Type) where -- much like the above but done by hand
toMonoid : Monoid α
toGroup : Group α
example {α : Type} [Ring α] : (Ring.toMonoid.op : α → α → α) = Ring.toGroup.op :=
rfl -- fails
end pig2
Andy Soffer (May 13 2024 at 01:17):
This is a reasonable workaround, but comes with a tradeoff I don't really like, which is that I don't get the field merging when I want it. Without it as I build up each class I need to effectively determine all the fields I would want transitively and place them in each class, since I'm not getting them via inheritance.
I guess I was hoping for something like being able to annotate fields as private so they'd be accessible explicitly via myRing.toGroup.op
but have the others merged.
Kim Morrison (May 13 2024 at 01:26):
Nothing like this exists at present.
Kyle Miller (May 13 2024 at 01:26):
One could imagine, for example, having Monoid and Group classes each with an
op
field, and wanting them to be coalesced in some cases, but not for Ring where the Monoid is for multiplication and the group is the additive group.
The way this is done in practice (in mathlib) is to have AddGroup
, which has its own add
field and +
notation, and Monoid
, which has its own mul
field and *
notation.
Do you have other concrete use cases for this?
A. (May 13 2024 at 08:15):
I remember now that what surprised me was the merging of fields that hadn't been introduced through the extends
mechanism. I wonder would anything be lost if merging were restricted to such fields only? So that pig1
would no longer work but this pig3
still would.
namespace pig3
class Op (α : Type) where op : α → α → α
class Monoid (α : Type) extends Op α
class Group (α : Type) extends Op α
class Ring (α : Type) extends Monoid α, Group α
example {α : Type} [Ring α] : (Ring.toMonoid.toOp : Op α) = Ring.toGroup.toOp :=
rfl
end pig3
Andy Soffer (May 13 2024 at 15:54):
No other use cases (all flavors of this problem). There are definitely solutions in practice... I'm really just playing around and trying things out.
Thanks for the help!
Last updated: May 02 2025 at 03:31 UTC