Zulip Chat Archive

Stream: mathlib4

Topic: Classes design and instances


Sebastien Gouezel (Feb 11 2023 at 08:34):

I have a bunch of questions on the design of classes in mathlib4, and I hope someone could help me clarify my thoughts.

The implementation of classes is new style, but this is hidden from the user who may think that everything is flattened (i.e., old style). Assume that you have a class with data A_data and then classes that add new Prop properties, say B_prop that extends A_data and then C_prop that extends B_prop and D_prop that extends C_prop. From an API point of view, saying that D_prop is defined as (1) extends A_data, C_prop or (2) extends C_prop or (3) extends C_prop, A_data is the same, but it's not from an inner implementation point of view. If I understand correctly, in (1) there would be a field to_A_data containing the data, and then flattened copies of the additional axioms in B and C, and a field with the addtional D axiom, and the creation of a to_C map (which would not be a field of the structure). While (2) and (3) would be internally the same, with a field to_C and a field with the additional axiom of D (and in (3) the creation of an additional map to_A). Am I correct here? Is there a way to see the internals of the things Lean4 generates when one declares a class like that?

Sebastien Gouezel (Feb 11 2023 at 08:39):

Then there are diamond-like situations, where there is another class C'_prop extending B_prop, and then D_prop extends both C_prop and C'_prop. Say that one defines it as (1) extends A_data, C_prop, C'_prop or (2) extends C_prop, C'_prop. In the first case, one gets a field to_A and flattened copies of the additional axioms, while in (2) one gets a to_C and flattened copies of the additional axioms of C', again if I get it right.

Sebastien Gouezel (Feb 11 2023 at 08:41):

No my question is what happens when one creates instances of the classes, and if the order there is relevant. For instance if you create an instance of D having already instances of C and C', will things be nice if you declare it like with already_defined C, already_defined C' and bad if you change the order to with already_declared_C', already_declared_C? (With, in the second case, the map to C borrowing the data field from already_declared_C' and the axiom from already_declared_C)?

Sebastien Gouezel (Feb 11 2023 at 08:43):

Again, is there a way to check the internals of how Lean 4 has implemented a structure declaration?

Sebastian Ullrich (Feb 11 2023 at 09:08):

#print on the class will tell you the exact fields

Sebastien Gouezel (Feb 11 2023 at 10:17):

Would the following design be reasonable? There would be classes carrying only data -- for instance, for semirings, semiring_data would have zero, one, addition, multiplication. And then the real classes need a bunch of properties depending on the data, which could be put into a single Prop-valued substructure. The interest is that when checking that two ring structures coincide, first you need to check that the data coincide, of course, but then by proof irrelevance you would only need to check that the type of the single Prop-valued field is the same, which amounts to checking once again that the data coincide -- just one check, instead of many many checks currently, one for each axiom.

Of course, with this design ring would internally not be defined as extends semiring, but instead ring_data would extend semiring_data, and the map from ring to semiring would not be a field of the structure. (And this would need serious engineering to hide that from the users, and to give the impression that fields of the Prop-substructure are normal fields). The data for comm_ring and ring would be the same, though, so following strings of reductions would be pretty quick.

I wonder if this wouldn't be much more efficient than what we do currently. Not in the near future, of course, because there are much more urgent things, but still I'd be interested in your thoughts.

Eric Wieser (Feb 11 2023 at 10:46):

I think this is what Agda does

Eric Wieser (Feb 11 2023 at 10:48):

One advantage of that approach is that if you need an intersection typeclass that doesn't exist, you can use [ring_data R] [is_normed_ring R] [is_linear_ordered_ring R]


Last updated: Dec 20 2023 at 11:08 UTC