Google Groups no longer supports new Usenet posts or subscriptions. Historical content remains viewable.
Dismiss

how typish are roles

5 views
Skip to first unread message

TSa

unread,
Oct 25, 2006, 3:19:49 AM10/25/06
to p6l
HaloO,

from the recent threads 'class interface of roles',
'set operations for roles' and 'signature subtyping
and role merging' I wonder how typish roles actually
are. Some seem to consider roles as lightweight
particles that serve to compose classes. I see them
as the heavyweights in the type department. Doing a
role is like a contract about certain functionality.
So, what does @Larry think?

I know that S12 states "The type system of Perl
consists of roles, classes, and subtypes" but I don't
have a clear picture of the inner workings or the
formal model of this type system. E.g. what actually
constitutes a type? How are the classes related to
types? There is this fuzzy concept that a class is
also a role of the same name as far as typing is
concerned. How is the subtyping relation defined?


Regards, TSa.
--

Trey Harris

unread,
Oct 25, 2006, 6:04:17 AM10/25/06
to TSa, p6l
In a message dated Wed, 25 Oct 2006, TSa writes:

> from the recent threads 'class interface of roles', 'set operations for
> roles' and 'signature subtyping and role merging' I wonder how typish
> roles actually are. Some seem to consider roles as lightweight particles
> that serve to compose classes. I see them as the heavyweights in the
> type department. Doing a role is like a contract about certain
> functionality. So, what does @Larry think?

I'll let @Larry speak for @Larry, but at one point I was told that when
C<Array> or C<Hash> appear in signatures, those are roles, not classes; if
you examined a particular Array or Hash, the class would be some
implementation of the Array or Hash role, perhaps something like
C<PugsSparseArray> or C<ParrotOpaqueHash> or so on. So I'd tend to agree
that roles "are the heavyweights in the type department."

I've spent a few minutes with no luck trying to draw the actual discussion
out of the #perl6 logger, but I'm pretty sure this was the gist.

My (probably lame) interpretation of the Weltanschauung of Perl's typing
is that roles, classes, type parameters, and type sets (junctive types,
subsets, and mixtures thereof) are all equally relevant to the type
system, and are all equally "typish" (though perhaps some are more
primitive and some are more sugary).

Unless you're actually composing or inheriting from something, you
shouldn't care whether its type derives from a role, a class, a type set,
or a type parameter. (And if you are composing or inheriting from it,
you're not so much interested in its typishness as its behavior. Your new
type will be/do whatever type(s) it inherited/composed, and will also
be/do itself; beyond that, you shouldn't care....)

My gut feeling is that in real-world Perl 6 code we'll see a lot of both
classes and roles being used as types. Roles will be more common typing
particles when interacting with the Perl core or parts of other large code
bases, and when you desire type safety. Classes will be more common when
you just have a local need to have something to instantiate, or you want
SMD or MMD. When programming in the large, the benefits of having a role
will often be clearer; when programming in the small, a class will often
(C<but> not always ;) be more expeditious.

I think the question (which you didn't directly raise, but I've heard from
others) of whether "role" or "class" will have primacy is kind of as
pointless as asking whether "subroutines" or "code blocks" have primacy:
you can't use the former without the latter; the former is a useful
abstraction for the latter, especially when code gets larger or is meant
for sharing; and while each have places where they're more appropriate,
either can be used in place of the other given a bit of syntactic
twiddling.

> I know that S12 states "The type system of Perl consists of roles,
> classes, and subtypes" but I don't have a clear picture of the inner
> workings or the formal model of this type system. E.g. what actually
> constitutes a type? How are the classes related to types? There is this
> fuzzy concept that a class is also a role of the same name as far as
> typing is concerned. How is the subtyping relation defined?

I can read S12 as saying that classes always do an eponymous role, and so
role is what typing is "really" based on. Or alternatively, since when a
role is used as if it were a class, it constructs an anonymous class that
composes it, that class is what typing is "really" based on. But I don't
see that it matters one way or the other; they seem functionally
equivalent to me--as would having type based on C<where> subsets, or
having all these things participate equally, or any other angle you might
want to look at it from. The behavior seems pretty ecumenical to me.

In other words, I agree that it's fuzzy, but I personally read the
fuziness as intentional, so as to allow implementations flexibility and
prevent bad dependencies on particular "inner workings" of the type
system.

Trey

TSa

unread,
Oct 25, 2006, 10:39:03 AM10/25/06
to p6l
HaloO,

Trey Harris wrote:
> In other words, I agree that it's fuzzy, but I personally read the
> fuziness as intentional, so as to allow implementations flexibility and
> prevent bad dependencies on particular "inner workings" of the type system.

Thanks for the support. I figured that I've asked the same question more
than a year ago. I want to summarize what we have so far.

1) In type constraint position we can say things like A|B to effectively
mean a supertype of A and B by virtue of $_ ~~ A || $_ ~~ B.

2) We have A&B and the A B juxtaposition to mean $_ ~~ A && $_ ~~ B
which is an intersection (sub)type of A and B.

3) The junctive ops |, & and ^ can be used in where clauses to form
type constraints. How does that apply to any(), all(), one() and
none()? Are they allowed as well? With none() we effectively get
type complement.

4) The junctive ops and the set operators (|) and (&) are *not* yet
available as type constructors in role definitions, that is things
like 'role does A(&)B'. To comply with 2) this should create an
intersection type even though it joins the interfaces of A and B.

Does recursive use of roles in their own definition produce F-bounds?

role A does Gen[A] {...}

or perhaps

role A where A.does(Gen[A]) {...}


Regards, TSa.
--

Jonathan Lang

unread,
Oct 25, 2006, 8:14:52 PM10/25/06
to perl6language
TSa wrote:
> I want to summarize what we have so far.
>
> 1) In type constraint position we can say things like A|B to effectively
> mean a supertype of A and B by virtue of $_ ~~ A || $_ ~~ B.

Right. This would be equivalent to "Any where {.does(A) or .does(B)}".

> 2) We have A&B and the A B juxtaposition to mean $_ ~~ A && $_ ~~ B
> which is an intersection (sub)type of A and B.

Not according to my reading of S06: if you want to force a parameter
to match both of two different roles, you must use a where clause.

> 3) The junctive ops |, & and ^ can be used in where clauses to form
> type constraints. How does that apply to any(), all(), one() and
> none()? Are they allowed as well? With none() we effectively get
> type complement.

AFAICT, any() can be used (almost) anywhere that infix:<|> can be;
ditto with the other junctive ops and their associated functions. In
particular, I see no reason why they would be forbidden in where
clauses. (The one case where "any" might not be usable as a
substitute for infix:<|> is point 1, above. Even then, I'm not really
certain that it can't be used.)

> 4) The junctive ops and the set operators (|) and (&) are *not* yet
> available as type constructors in role definitions, that is things
> like 'role does A(&)B'.

Correct. If there's a queue being maintained for post 6.0 features,
I'm hoping that it's in the queue; but it isn't going to be a 6.0
feature AFAIK.

> Does recursive use of roles in their own definition produce F-bounds?
>
> role A does Gen[A] {...}

I don't see why not. Heck, while it would usually be silly to do so,
I could even see cyclic role definitions working:

role A does B { ... }
role B does A { ... }

or even

role A does A { ... }

(though why any role would ever want to compose itself is beyond me.)

--
Jonathan "Dataweaver" Lang

TSa

unread,
Oct 26, 2006, 3:45:54 AM10/26/06
to perl6language
HaloO,

Jonathan Lang wrote:
>> 2) We have A&B and the A B juxtaposition to mean $_ ~~ A && $_ ~~ B
>> which is an intersection (sub)type of A and B.
>
> Not according to my reading of S06: if you want to force a parameter
> to match both of two different roles, you must use a where clause.

In section "Polymorphic types" S06 reads: "Since the terms in a
parameter could be viewed as a set of constraints that are implicitly
"anded" together (the variable itself supplies type constraints, and
where clauses or tree matching just add more constraints), we relax this
to allow juxtaposition of types to act like an "and" junction:"
The following example also makes it clear that a joined interface
is meant. So I think a where clause it not needed.

Regards, TSa.
--

TSa

unread,
Oct 26, 2006, 9:17:27 AM10/26/06
to p6l
HaloO,

I wrote:
> 2) We have A&B and the A B juxtaposition to mean $_ ~~ A && $_ ~~ B
> which is an intersection (sub)type of A and B.

Is the A&B form a legal alternative for the juxtaposition?
--

Chromatic

unread,
Oct 28, 2006, 3:01:39 AM10/28/06
to perl6-l...@perl.org, Trey Harris, TSa
On Wednesday 25 October 2006 03:04, Trey Harris wrote:

> I'll let @Larry speak for @Larry, but at one point I was told that when
> C<Array> or C<Hash> appear in signatures, those are roles, not classes; if
> you examined a particular Array or Hash, the class would be some
> implementation of the Array or Hash role, perhaps something like
> C<PugsSparseArray> or C<ParrotOpaqueHash> or so on. So I'd tend to agree
> that roles "are the heavyweights in the type department."

Yes.

When you specify a type to constrain some operation, you specify that the
target entity must perform that role.

> Unless you're actually composing or inheriting from something, you
> shouldn't care whether its type derives from a role, a class, a type set,
> or a type parameter.

Yes.


> I think the question (which you didn't directly raise, but I've heard from
> others) of whether "role" or "class" will have primacy is kind of as
> pointless as asking whether "subroutines" or "code blocks" have primacy:
> you can't use the former without the latter; the former is a useful
> abstraction for the latter, especially when code gets larger or is meant
> for sharing; and while each have places where they're more appropriate,
> either can be used in place of the other given a bit of syntactic
> twiddling.

Well... maybe. I believe strongly that you can build a really good system
with roles as the fundamental abstraction and where classes are a
specialization, but doing the other way around is much more difficult and
less cohesive.

> I can read S12 as saying that classes always do an eponymous role, and so
> role is what typing is "really" based on.

Yes.

> In other words, I agree that it's fuzzy, but I personally read the
> fuziness as intentional, so as to allow implementations flexibility and
> prevent bad dependencies on particular "inner workings" of the type
> system.

That fuzziness is classic $Larry. Some of the rest of @Larry can be more
*mumble*matic.

-- c

Trey Harris

unread,
Oct 28, 2006, 7:50:43 AM10/28/06
to chromatic, perl6-l...@perl.org, TSa
In a message dated Sat, 28 Oct 2006, chromatic writes:
> When you specify a type to constrain some operation, you specify that
> the target entity must perform that role.

That statement is very concise and direct. If the fuzziness I observed
about the identity of the basic building block of type was unintentional,
this statement should be added to S06.

>> I think the question (which you didn't directly raise, but I've heard
>> from others) of whether "role" or "class" will have primacy is kind of
>> as pointless as asking whether "subroutines" or "code blocks" have
>> primacy: you can't use the former without the latter; the former is a
>> useful abstraction for the latter, especially when code gets larger or
>> is meant for sharing; and while each have places where they're more
>> appropriate, either can be used in place of the other given a bit of
>> syntactic twiddling.
>
> Well... maybe. I believe strongly that you can build a really good
> system with roles as the fundamental abstraction and where classes are a
> specialization, but doing the other way around is much more difficult
> and less cohesive.

But I wasn't suggesting that, any more than I was suggesting that code
blocks based on anonymous subroutines would be as cohesive as subroutines
based on code blocks. I was just saying that both roles and classes could
be equally first-class participants in the type system by my reading of
S06 and S12: I don't see any necessity, short a statement like yours I
quoted above, for classes to be coerced into a role before they can act as
a type.

Trey

Trey Harris

unread,
Oct 28, 2006, 8:52:54 AM10/28/06
to chromatic, perl6-l...@perl.org, TSa
In a message dated Sat, 28 Oct 2006, Trey Harris writes:

> In a message dated Sat, 28 Oct 2006, chromatic writes:
>> When you specify a type to constrain some operation, you specify that the
>> target entity must perform that role.
>
> That statement is very concise and direct. If the fuzziness I observed about
> the identity of the basic building block of type was unintentional, this
> statement should be added to S06.

Incidentally, this would mean that a C<where> clause or junctive type
defines an anonymous role, and a type parameter defines a lexical role,
doesn't it? Seems like a useful characteristic of these constructs to
make explicit, perhaps in L<S12/Roles>.

I find this a little unintuitive given the way these typing particles are
used, though... If I were insane in a different way than I actually am, I
might think I could use this "every constraint is a role" behavior to
write:

sub pairs_up_to (Int $x where { $^x % 2 == 0 } ) {
(1..^$x:by(2)) >>=><< (2..$x:by(2))
}

pairs_up_to(4)}; # 1 => 2, 3 => 4

try { pairs_up_to(3) }
err say $!; # "No compatible subroutine found"

my $even_three = 3 but where { $_ % 2 == 0 }; # Huh?
try { pairs_up_to($even_three) }
err say $!; # What?

Not a useful example, I admit--which is why I had assumed C<where>
constraints were not roles, because I can't think of a useful example of
treating them as roles. But I suppose if you're determined to shoot
yourself in the foot like that, you'll find some way (like overloading
C<%> so it always returns 0).

You could probably even make Perl be able to call the sub in the second
C<try>, perhaps by making the anonymous roles generated by C<where> first
match by AST equivalence before testing their value against the constraint
or something.

Not that I think Perl should be able to do that... I'm just saying I
*might* think it would, given how roles usually work (and if I could come
up with a less contrived case, I might actually expect it to).

But *why* wouldn't it work? One of two reasons I think:

1. The first C<where> clause in the sub signature defines a different
anonymous role from the second C<where> clause after C<but>, even
though they're defined identically. In that case, $even_three would
have no practical difference from any other 3, because it merely mixes
in a role that never gets used.

2. The assignment would throw a mistyped value exception, just like
"my Num $foo = 'hi, mom'" does. (Except it doesn't. Should it? I
don't see a test that addresses this in the suite, nor something in
the Synopses to say that that assignment should fail.)

In either case, C<where> clauses create roles that values might do without
even realizing they're doing them, and which mutable objects might do and
then not do, willy-nilly, even in the course of the scope in which they
were typed to do it... which I think is new unless I just haven't been
paying attention.

sub saturate (Color $c where { $^c.saturation < 100 } ) {
$c.saturation = 100; # ???
correct_gama($c);
}

Did that mutation throw an exception, by changing $c's type to one it
can't have in this sub? If no, did we just lose gradual typing (assuming
correct_gamma cares)? Can we detect that, or do the roles created by
C<where> not participate in gradual typing? If C<where> constraints
weren't roles, this would make sense to me again.

It's duck-typing, but a very different type of duck typing than, say Ruby
has... it isn't a duck because it walks and quacks, but because when you
examine it with your particular duckish litmus test (your C<where>
clause), the litmus test turns the duckish color (Bool::True) you're
looking for.

A trifling issue, I guess, as you can just ignore how C<where> works so
long as it does work. But when I see a statement like "every X is really
syntactic sugar for a Y", I want to poke at all the X's to see how they
behave deeply as Y's.

Trey

Larry Wall

unread,
Oct 28, 2006, 12:15:41 PM10/28/06
to perl6-l...@perl.org
My initial inclination is to say that "where" clauses in a signature
are only there for pattern matching, and do not modify the official
type of the parameter within the function body. However, on a "subset"
the "where" clause is there precisely to contribute to the typing,
so if you want the extra constraints to apply to all uses of the
parameter variable within the body, you'd need to declare a subset
type that enforces it.

On the other hand, I can imagine that an alternative would be to say
that a "where" clause will always "subsetize" the official type;
that would imply that we'd need to add a "when" clause for mere
pattern matching. Something to be said for making such a distinction,
if it can be taught.

Fuzzily yours,
Larry

Larry Wall

unread,
Oct 28, 2006, 12:19:58 PM10/28/06
to p6l
On Thu, Oct 26, 2006 at 03:17:27PM +0200, TSa wrote:
: HaloO,

Not in a signature. It's ambiguous with A &B where &B is declaring a
routine type that returns A. Might be made to work in parens someday.
But I'm still somewhat set against the notion of using logical ops to
do set theory. (Even if you put parens around them.)

Larry

Jonathan Lang

unread,
Oct 28, 2006, 12:49:34 PM10/28/06
to p6l
Larry Wall wrote:
> But I'm still somewhat set against the notion of using logical ops to
> do set theory. (Even if you put parens around them.)

Understandably so. Perhaps "(u)" and "(n)" would be better ASCII
equivalents for the union and intersection operators...

--
Jonathan "Dataweaver" Lang

Jonathan Lang

unread,
Oct 28, 2006, 12:43:29 PM10/28/06
to perl6language
Trey Harris wrote:

> Trey Harris writes:
> > chromatic writes:
> >> When you specify a type to constrain some operation, you specify that the
> >> target entity must perform that role.
> >
> > That statement is very concise and direct. If the fuzziness I observed about
> > the identity of the basic building block of type was unintentional, this
> > statement should be added to S06.

S02 already has q[A variable's type is a constraint indicating what
sorts of values the variable may contain. More precisely, it's a
promise that the object or objects contained in the variable are
capable of responding to the methods of the indicated "role".]

> Incidentally, this would mean that a C<where> clause or junctive type
> defines an anonymous role, and a type parameter defines a lexical role,
> doesn't it? Seems like a useful characteristic of these constructs to
> make explicit, perhaps in L<S12/Roles>.

IMHO, this gets it backward. You shouldn't turn C<where> clauses and
junctive types into roles; you should turn roles and junctive types
into C<where> constraints: "Foo $x" is, in effect, shorthand for
something like "$x where { .does(Foo) }", while "Foo | Bar Baz $x"
becomes something like "$x where { .does(Foo) || .does(Bar) &&
.does(Baz) }".

At its core, a type is nothing more than a constraint on the objects
that a given variable is allowed to handle; this would put C<where>
clauses at the center of the type system, with roles coming in a very
close second due to the implicit use of ".does()" in the compact
syntax. IMHO, @Larry got overly precise in the above S02 quote:
s[More precisely] = "Usually".

--
Jonathan "Dataweaver" Lang

Chromatic

unread,
Oct 28, 2006, 2:41:29 PM10/28/06
to perl6-l...@perl.org, Larry Wall
On Saturday 28 October 2006 09:15, Larry Wall wrote:

> My initial inclination is to say that "where" clauses in a signature
> are only there for pattern matching, and do not modify the official
> type of the parameter within the function body.  However, on a "subset"
> the "where" clause is there precisely to contribute to the typing,
> so if you want the extra constraints to apply to all uses of the
> parameter variable within the body, you'd need to declare a subset
> type that enforces it.

Right; it's awfully difficult to have nominal typing in a room full of
blank "Hello my name is" tags.

> On the other hand, I can imagine that an alternative would be to say
> that a "where" clause will always "subsetize" the official type;
> that would imply that we'd need to add a "when" clause for mere
> pattern matching.  Something to be said for making such a distinction,
> if it can be taught.

-- c

TSa

unread,
Oct 30, 2006, 8:59:59 AM10/30/06
to p6l
HaloO,

Jonathan Lang wrote:
> Larry Wall wrote:
>> But I'm still somewhat set against the notion of using logical ops to
>> do set theory. (Even if you put parens around them.)
>
> Understandably so. Perhaps "(u)" and "(n)" would be better ASCII
> equivalents for the union and intersection operators...

Hmm, I think using the dualism between set operations and
boolean operations is a good thing. Note that there is an
isomorphism between &&, || and ! for the logical side and
(&), (|) and (!) for sets---DeMorgan etc. We could even
introduce low precedence versions (and), (or) and (not).
Well, and of course (^) and (xor) corresponding to ^^ and
xor. They all form nice mnemonics for each other.


Regards, TSa.
--

TSa

unread,
Oct 30, 2006, 10:16:57 AM10/30/06
to perl6language
HaloO,

Jonathan Lang wrote:
> At its core, a type is nothing more than a constraint on the objects
> that a given variable is allowed to handle; this would put C<where>
> clauses at the center of the type system, with roles coming in a very
> close second due to the implicit use of ".does()" in the compact
> syntax.

Great idea! I like the unification of everything typish under the
umbrella of (type) constraints. These predicates then need to be
amenable to subsumption and entailment forming the dispatch lattice.
Of course the sublanguage for where clauses has to be a restricted
subset of full Perl 6. Otherwise you can't do machine proofs. This
view is shared by mmd-draft.txt, it states that conceptually all
dispatch relevant informations are predicates.

Hmm, having regular expressions in where clauses already raises
the question if one can treat them programatically. E.g. a
'where /^aa.*bb$/' is strictly more specific than 'where /^a.*b$/'.
But can that be calculated in a deterministic fashion? Would
dispatch at least work on a case by case basis? Or would we get
ambiguity errors because of principal incomparability of the two
clauses? IOW, I fear this could only be put to work with two subset
declarations

subset ab of Str where /^a.*b$/;
subset aabb of ab where /^aa.*bb$/;

and the notion that the second subset by virtue of constraining
the possible values further produces a more specific subtype for
dispatch. That is nominal subtyping.

BTW, the above example is a good case for introducing the subtype
relation operator <: because we have aabb <: ab <: Str but do we
also have aabb.does(ab) and ab.does(Str)? Could we also state that
aabb (<) ab (<) Str?


Regards, TSa.
--

Jonathan Lang

unread,
Oct 30, 2006, 10:55:48 AM10/30/06
to p6l
TSa wrote:
> IOW, I fear this could only be put to work with two subset
> declarations
>
> subset ab of Str where /^a.*b$/;
> subset aabb of ab where /^aa.*bb$/;
>
> and the notion that the second subset by virtue of constraining
> the possible values further produces a more specific subtype for
> dispatch. That is nominal subtyping.

Perl 6 already uses nominal subtyping: S02 - "Types are officially
compared using name equivalence rather than structural equivalence."
There's further elaboration which addresses many of the concerns
involved with using nominal subtyping, so I'd suggest reading the
section in question before commenting.

> BTW, the above example is a good case for introducing the subtype
> relation operator <: because we have aabb <: ab <: Str but do we
> also have aabb.does(ab) and ab.does(Str)? Could we also state that
> aabb (<) ab (<) Str?
>
>
> Regards, TSa.
> --
>


--
Jonathan "Dataweaver" Lang

Richard Liu

unread,
Oct 30, 2006, 11:09:56 AM10/30/06
to p6l
Hi,

G'day!

I am new to the Perl language. As a university student, I want to use perl to build some codes to work as tracing and automatic analysing tool with my data file in Linux environment. Could you kindly teach me which IDE tools should I use (freeware and shareware better :-) ) and what kind of debugger tools should I go through.

Any comments are truly appreciated. Thanks in advance!

Richard


---------------------------------
Do you Yahoo!?
Everyone is raving about the all-new Yahoo! Mail.

Jonathan Scott Duff

unread,
Oct 30, 2006, 11:57:56 AM10/30/06
to Richard Liu, p6l
On Mon, Oct 30, 2006 at 08:09:56AM -0800, Richard Liu wrote:
> I am new to the Perl language. As a university student, I want to
> use perl to build some codes to work as tracing and automatic
> analysing tool with my data file in Linux environment. Could you
> kindly teach me which IDE tools should I use (freeware and shareware
> better :-) ) and what kind of debugger tools should I go through.
>
> Any comments are truly appreciated. Thanks in advance!

Hi Richard! This mailing list is for discussion and development of
the Perl6 language. Since this language is still being designed, you
probably want to know about Perl5 resources. A good place to start
would be http://learn.perl.org/. Also, you might want to try on IRC.
There's #perl on the freenode network and #perlhelp on efnet.

hope this helps,

-Scott
--
Jonathan Scott Duff <du...@pobox.com>

0 new messages