[Python-3000] my take on "typeclasses"

Phillip J. Eby pje at telecommunity.com
Fri May 12 18:21:51 CEST 2006


At 10:14 PM 5/11/2006 -0700, Talin <talin at acm.org> wrote:
>Marcin 'Qrczak' Kowalczyk wrote:
> > Talin <talin at acm.org> writes:
> >>   # Use as a function argument constraint
> >>   @generic
> >>   def flatten( x:concepts.iterable ):
> >>      ...
> >>
> >>   # Another overload
> >>   @generic
> >>   def flatten( x:concepts.associative ):
> >
> > How are concepts defined?
>
>Each concept is essentially a class, written in either Python or C, that
>defines a set of tests, and a set of introspection methods.

Note that they don't need to be classes.  Last night I checked in a sketch 
of extensible overloading:

     http://svn.python.org/projects/sandbox/trunk/Overload3K/

The doctest (overloading.txt) has an example of using a 1-argument 
overloaded function as a "concept", such that if the function can be called 
with an argument of that type, then it is considered to be of that type 
when dispatching.

I didn't have time to include overloading of built-in functions, so it uses 
a 'my_iter' function to be able to demo the "flatten()" use case.  I hope 
to add overloading of builtins (like iter()) tonight or over the weekend.

As currently written, the sketch will work with any sort of concept 
implementation you can come up with, as long as the concept relies only on 
tests that can be applied to an object's *type*, because the dispatching is 
based on a refactoring of Guido's overloaded function implementation, which 
relies on type-tuple caching for performance.

Basically, what I did is take Guido's implementation and then replace all 
of the hardcoded MRO manipulation with a single overloaded function, 
'implies()'.  The implies() function can be used to test dominance between 
signatures, or to test whether a signature applies to the invoked type 
signature.  There is also a second overloaded function, 'type_matches()', 
which is basically an overloadable form of 'issubclass()'.

With these minor alterations, the basic overloading machinery can now be 
used with any "concept" objects you care to implement.  All you have to do 
is define 'implies()' or 'type_matches()' methods for any combinations of 
concept and type that might need to be examined.

For example, the sketch defines overloads equivalent to these two declarations:

      defop type_matches(g1:overloaded, g2:overloaded)

      defop type_matches(g1:type, g2:overloaded)

These definitions allow two overloaded functions to be tested for which is 
more specific than the other, and allows a type to be tested against an 
overloaded function to see if it's suitable.

If you were to define a new 'concept' type, you would need to implement 
these methods:

      defop type_matches(g1:concept, g2:concept)

      defop type_matches(g1:type, g2:concept)

      defop type_matches(g1:concept, g2:overloaded)

      defop type_matches(g1:overload, g2:concept)

and if it's possible for a concept to imply a type, you would also need:

      defop type_matches(g1:concept, g2:type)

But once you had the methods, you would be able to freely mix your new 
concept implementation with other types in a function's signature for 
overloading purposes.

Note that these concept objects could be today's protocol or interface 
objects, or even arbitrary data like numbers or strings.  As long as you 
can define the appropriate set of 'type_matches' to allow signature matches 
and dominance to be computed, everything's super.  (No pun intended.)



More information about the Python-3000 mailing list