On 10/28/05, Christopher D. Malon <[EMAIL PROTECTED]> wrote:
> On Oct 28, 2005, at 11:13 PM, Luke Palmer wrote:
> Trying to think through the VectorSpace example, and a slightly
> more complicated example (a Field), I'm starting to wonder whether
> roles need to be parameterized somehow.  (Maybe they already are?
> This is one of my first p6 attempts, so bear with me...)

Oh yeah, roles can be parameterized.

    role VectorSpace[Field ^f] {...}
    role Field[AbelianGroup ^plus, Group ^times] {...}

I'm intentionally handwaving over some details that are important.  See below.

> role Group should define a method "inverse()" whose implementation
> is up to the class.  inverse(operation => '+') or inverse(operation
> => '*')
> would make perfect sense.  On an object that does Group only one way,
> inverse() by itself would be okay, but it would be ambiguous
> on a Field object.  I don't know whether it's better for the interpreter
> to produce a run-time error when a class implements a role in two ways
> and the parameter isn't supplied, or if one implementation of a role
> should
> take priority.

This is indeed the problem.  A related problem is, let's say you have
a utility sub for groups:

    # Group $x meaining an element of a group... that's a little strange
    sub power(Group $x, Int $pow) {
        given $pow {
            when $_ <  0  { power(inverse($x), -$pow) }
            when $_ == 0  { identity() }
            when $_ >  0  { $x * power($x, $pow - 1) }
        }
    }

But what if you have a set that is a group under addition?  That
doesn't work, since you're trying to multiply here.

    sub power(Group[&infix:<*>] $x, Int $pow) {
        # same body as before
    }

That assumes that Group has one parameter: the operation under which
it is a group.  Then you *bind* that parameter to a lexical infix:<*>,
which means that when you say * within the body of your subroutine,
you actually mean whatever operation the group defines.

However, we still have a problem when we give a Field to power.  Which
group do we mean?  One way to do this would be to pass an optional
parameter: an object describing the group:

    sub power(Group $x, Int $pow, GroupDesc $desc = $x.desc) {
        given $pow {
            when $_ <  0  { power($desc.inverse($x), -$pow, $desc) }
            when $_ == 0  { $desc.identity }
            when $_ >  0  { $x * $desc.power($x, $pow - 1, $desc) }
        }
    }

But that's starting to take away from the readability of the code, and
it really takes away from the fact that Group is encoding the
structure.

There was a proposal in Haskell to have what they called "named
instances", which addresses these kinds of problems:

    http://www.informatik.uni-bonn.de/~ralf/hw2001/4.pdf

Perlizing the proposal, we might have something like:

    role Field[&infix:<+>, &infix:<*>] {
        does Group[&infix:<+>] FieldPlus;
        does Group[&infix:<*>] FieldTimes;
        ...
    }

    power(4, 3) (FieldPlus);   # 12
    power(4, 3) (FieldTimes);  # 256

All group operations on a field would be on the Plus group if we're in
a FieldPlus context, and conversely, all group operations on the field
would be on the Times group if we're in a FieldTimes context.

Exploring this issue further could be important to Perl's power when
it comes to automatic dispatch.

Luke

Reply via email to