Aahz <[EMAIL PROTECTED]> wrote: ... > Hrm. I don't recall anything about typeclasses, so my suspicion is that > you were writing something lengthy and above my head. Can you write > something reasonably short about it? (I'm asking partly for your > benefit, because if it makes sense to me, that will likely go a long way > toward making sense to Guido -- we seem to think similarly in certain > ways.)
Think of a typeclass as something "like an interface, more than an interface" to which a type can easily be "adapted" by a third programmer even if the two programmers who wrote the type and typeclass were working separately and with no knowledge of each other -- not too far from the vaguer idea of "protocol" I support in PEP 246 (which focuses on the adaptation), except that in Haskell things happen at compile time while in Python we prefer to avoid the strong distinction between compile time and runtime. You may think of a typeclass as akin to an abstract baseclass, because it's not constrained to only giving the signatures of methods, it can also supply some default implementations of some methods in terms of others. Guido blogged in August about interfaces versus ABCs, not remembering why he had once Pronounced about preferring ABCs, and in his critique of ABCs he mentions that one weakness of their ability to provide default implementations is that you have to decide about what is the most fundamental subset, in whose terms the rest is implemented. But *typeclasses do away with that need*. Consider (arbitrary pythonesquoid syntax): typeclass mapping: def __getitem__(self, key): _notthere=[] result = self.get(key, _notthere) if result is notthere: raise KeyError return result def get(self, key, default): try: return self[key] except KeyError: return default # etc etc this LOOKS like mutual recursion, but since it's a typeclass it doesn't mean that: it means __getitem__ may be defined (and then get uses the provided default implementation unless overridden) OR get may be defined (and then it's __getitem__ that may use the default implementation supplied by the the typeclass, or else override it). When you compile a typeclass you build a directed graph of dependencies of methods on each other, which may include cycles; when you show how a type adapts to a typeclass, you build a copy of that graph removing the dependencies of those methods which do get explicitly implemented (in the type or in the adapter) -- if the copy at the end of these compilations still has cycles, or leaves (methods that the typeclass requires and neither the type nor the adapter supply), then this raises an exception (incomplete adaptation). Thus, a typeclass clearly shows the semantics intended for methods that depend on each other, and conveniently lets you, the adapter's author, choose what to implement -- the typeclass's author has not been forced to pick the "most fundamental" methods. ABCs, or extremely handy mixins such as UserDict.DictMixin, do force a programmer who knows nothing about the internals of your class (the author of the ABC or mixin) to pick "most fundamental" methods. Thus, typeclasses are more useful than ABCs by as much as ABC are more useful than (simply "syntactical") interfaces -- coupled with adaptation mechanisms, the overall result can be extremely handy (as any Haskell programmer might confirm). Alex -- http://mail.python.org/mailman/listinfo/python-list