Feedback: Self
type member makes mixin givens less compositional
#20366
Labels
stat:needs triage
Every issue needs to have an "area" and "itype" label
Compiler version
Latest
main
branch,3393f7ea7704eb1dd553c96a805906821c61db5f
.Feedback
This is some specific feedback from the first day of experimenting with the newly-merged
modularity
feature on an existing codebase of over 2000given
definitions. Wrt to the new typeclass encoding, the documentation says,which is true in many cases, but only when composing typeclass instances whose
Self
members have the same type. That is probably the majority of cases where there's justification for a singlegiven
to implement multiple typeclass interfaces, but it's not all.Here's a concrete example of an exceptional case. I want to use two typeclasses to generalize time, with a typeclass,
GenericInstant
representing instants in time, and another,GenericDuration
, representing durations. (Their abstract methods have different names, of course.)In the old style, I can create instances such as,
and with a single import of
myTimeApi
, a user can bring into scope a single instance which is aGenericInstant
and aGenericDuration
, and which are self-consistent. That is to say, the hypotheticalMyInstant
andMyDuration
types are designed to work harmoniously together. So the single-import is important for making it easy to use a family of types together. Put another way, I don't want to make it easy for users to pick potentially-incompatible types arbitrarily. (I believe this is the same motivation for the compositionality point from the documentation.)I have at least one other example of this relating to generic filesystem types (paths, files, directories).
A further issue
I've noticed a related issue while converting my existing typeclass definitions. I got into the habit of giving all my type parameters meaningful names (rather than just
T
) a while ago, which means that I can deduce the purpose of a type parameter or member easily from its name, using only very local reasoning. Instead, I'm now seeing the typeSelf
far too often, and it's not as immediately clear what it refers to. In more complex typeclasses (multiple parameters or many definitions) I have to look at the trait signature to deduce what theSelf
type represents, or infer its meaning from other places I see it used. This isn't an improvement.The name
Self
itself is fine for what it does, in general. But it only describes the privileged status of that type member with respect to using its enclosing typeclass in a context bound, and at the expense of it losing all other meaning. I might get used to this after spending longer with it, but if not, I'm likely to just add an extra type alias to every typeclass trait to ascribeSelf
a more meaningful name.A possible solution
I think that any mitigation of these issues would need to grant the freedom to choose the "Self" type's name, and other changes would follow to accommodate that. It's obviously not such a simple solution, but here's one suggestion for how that might work:
type
, saycontext
(or anything else), to mark a type member as "privileged" in context boundsis
definition magic so that it injects its left operand into thecontext type
of the right operandcontext
typecontext
type is defined in the same templateI don't see a problem with multiple
context type
s coexisting in the same template, as would be the case in a given instance ofGenericInstant & GenericDuration
. It would just be pointless to define them in the same body.The text was updated successfully, but these errors were encountered: