I've mentioned the concept of supertyping in several posts
but now I want to dedicate a thread to it because it increases
the expressive power of Perl 6 if one can form abstractions
not only by creating subclasses and subroles but also by going
in the other direction. Here are some use cases where this is

 Set <: Bag
 Set <: FuzzySet

 Num <: Complex <: Quaternion <: Octonion

 Vector <: Matrix <: Tensor

 Square <: Rectangle

The subtypes should be considered as given and the supertypes as
derived. Some code follows that explains how that might be done
for the Num <: Complex case. The key idea is that the ComplexRole
provides a default implementation of the .im accessor for Num.

role NumRole does Order
    multi infix:<+> ( Num $a, Num $b) {...}
    multi infix:<*> ( Num $a, Num $b) {...}
    method abs {...}

class Num does NumRole {...}

role ComplexRole superdoes Num # handwave, note that Complex doesn't
                               # do Order which is fine for a supertype
    method re { return self as Num } # noop for Num
    method im { return 0 }
    method abs {...}
    method arg { return self.re < 0 ?? pi !! 0 }
    multi infix:<+> ( Num $a, Num $b) {...}
    multi infix:<*> ( Num $a, Num $b) {...}

class Complex does ComplexRole
    # accessors overwrite role defaults
    has Num $.re;
    has Num $.im;
    multi infix:<+> ( Complex $a, Complex $b)
        return new Complex( $a.re + $b.re, $a.im + $b.im );
    multi infix:<*> ( Complex $a, Complex $b)
        return new Complex( $a.re * $b.re - $a.im * $b.im,
                            $a.re * $b.im + $a.im * $b.re );
    method abs { return sqrt( self.re**2 + self.im**2 ); }
    method arg
        if    self.im > 0 { return        acos( self.re / self.abs ); }
        elsif self.im < 0 { return 2*pi - acos( self.re / self.abs ); }
        elsif self.re < 0 { return pi; }
        else              { return 0; }

This works as far as the Complex numbers are defined in terms of the
.re and .im methods but fails as soon as you want them to be Complex constructors in lvalue context:

  use Complex;
  my $x = 3.2;
  $x.im = 1.2;   # becomes a non-real complex
  $x.arg = pi/4; # same

The question here is how the class Complex can receive the dispatch on
the Num class for putting a new Complex into $x. This is BTW yet another
example of changing an objects type while preserving its identity---see
the thread 'how to change the type of objects'. I mean here we have
value semantics anyway but in general a superclass might want to
preserve object identity while changing the type.

So will we have supertyping in Perl 6? If yes, how would my superdoes
be spelled? Same applies to a superis for classes.

Regards, TSa.

Reply via email to