On Oct 28, 2005, at 11:13 PM, Luke Palmer wrote:

Most certainly.  Implicit in a role or a theory is its algebra (though
we've talked about QuickCheckish ways to make it explicit).   For
instance, technically the VectorSpace theory only requires you to
define identity, addition, and scalar multiplication.  However, in
order to honestly do VectorSpace, addition has to be commutative,
which is something that the compiler usually is not able to check.

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...)

For the non-mathematically inclined:
A field is a set with two binary operations, + and *.
Under either operation (+ or *), the set is an abelian (= commutative) group,
and a field has a distributive property: a * (b + c) = a*b + a*c.
An easy example is the set of real numbers, with + being addition
and * being multiplication.

Now, I'd really like to say something like:

class RealNumbers does Field(addition => infix:<+>, multiplication => infix:<*>);

role Field {
  does AbelianGroup(operation => addition);
  does AbelianGroup(operation => multiplication);
}

Properties such as the distributive property are implicit
when a user asserts something is a Field, but the compiler
won't know about them.

To summarize so far:
1. The problem here is that a class has two distinct ways of
fulfilling the Group role, using methods that are named differently.
I want to keep these disambiguated, while benefitting from whatever
code comes for free when my class does Group.

2. The proposed solution is that, in order to "do" a role, I get to
provide a hash that describes, to the Role code, how it should
define its interfaces in terms of my class's variables and methods,
instead of assuming it will be able to look for particular names.

Now, the problem:

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.

Does this problem make sense, and is it solved already?

Christopher

Reply via email to