Re: not 4,3,2,1,0;
On Mon, May 16, 2005 at 04:06:15PM -0700, Larry Wall wrote: That's sub not (*args is context(Scalar)) or whatever we end up calling the Any/Scalar type. How about is context(Item) versus is context(Slurpy). :) Also, shouldn't the *args there be [EMAIL PROTECTED] Is it really okay to use a sigilless parameter name by default? Thanks, /Autrijus/ pgp4YJnETFxqi.pgp Description: PGP signature
Re: not 4,3,2,1,0;
On Tue, May 17, 2005 at 02:42:43PM +0800, Autrijus Tang wrote: : On Mon, May 16, 2005 at 04:06:15PM -0700, Larry Wall wrote: : That's : : sub not (*args is context(Scalar)) : : or whatever we end up calling the Any/Scalar type. : : How about is context(Item) versus is context(Slurpy). :) I've been kind of leaning towards Item lately for the Any type, but the other one could just be whatever we end up calling lazy lists, which is probably not Slurpy. : Also, shouldn't the *args there be [EMAIL PROTECTED] Is it really okay : to use a sigilless parameter name by default? Yes, that was just a typo. Larry
Re: not 4,3,2,1,0;
Larry Wall skribis 2005-05-17 1:24 (-0700): : How about is context(Item) versus is context(Slurpy). :) I've been kind of leaning towards Item lately for the Any type, but the other one could just be whatever we end up calling lazy lists, which is probably not Slurpy. Well, slurping and steam rolling are different things. Even slurp() can return a lazy list, and lazy lists don't mind going into a subroutine's slurpy array. List flattening doesn't (shouldn't) require immediate evaluation. I see no reason to not call it Slurpy. If there is any reason to not call it that, we also need new names for slurp() and slurpy parameters. Juerd -- http://convolution.nl/maak_juerd_blij.html http://convolution.nl/make_juerd_happy.html http://convolution.nl/gajigu_juerd_n.html
Quick question: '1.28' * '2.56'
Imagine: pugs '1.28' * '2.56' 3.2768 What is (or should be) going on here here? [1] role NumRole { method infix:* returns Num (NumRole $x, NumRole $y: ) { ... } } Str.does(NumRole); [2] multi sub infix:* (Str $x, Str $y) returns Num { ... } [3] multi sub prefix:+ (Str $x) returns Num { ... } multi sub infix:* (Num $x, Num $y) returns Num { ... } multi sub infix:* (Any $x, Any $y) returns Num { +$x * +$y } [4] multi sub infix:* (Num $x, Num $y) returns Num { +$x * +$y } # ...and the MMD dispatcher forces incompatible type into # the type with shared ancestors and closest distance... [5] none of the above -- that should be a type error. ;) [6] something else? Thanks /Autrijus/ pgp4AcX2zxMFU.pgp Description: PGP signature
Re: Quick question: '1.28' * '2.56'
On 5/17/05, Autrijus Tang [EMAIL PROTECTED] wrote: Imagine: pugs '1.28' * '2.56' 3.2768 What is (or should be) going on here here? ... [6] something else? I still don't quite have a handle on the object system. Maybe: subtype Num of Str where /^ number $/; ? Maybe s/Num/NumLike/ or something? Anyway, that's how I think of it at least: not that a Str is converted into a Num, but rather that certain Strs are Nums. Luke
Re: Quick question: '1.28' * '2.56'
Maybe s/Num/NumLike/ or something? Anyway, that's how I think of it at least: not that a Str is converted into a Num, but rather that certain Strs are Nums. If that's the case, then if I change a variable that isa Str (that isa Num), does it change what it inherits from? Rob
Re: Quick question: '1.28' * '2.56'
On 5/17/05, Rob Kinyon [EMAIL PROTECTED] wrote: Maybe s/Num/NumLike/ or something? Anyway, that's how I think of it at least: not that a Str is converted into a Num, but rather that certain Strs are Nums. If that's the case, then if I change a variable that isa Str (that isa Num), does it change what it inherits from? Er, Str is not a Num. Num is a subtype of Str, so Num is a Str. If you change a Str, it could cease to be a Num. $x = 123;# $x does Str Num Int $x .= .45; # $x does Str Num $x .= xyz; # $x does Str But again, don't take this as gospel. This is just a tidbit from the object model which I will probably not end up proposing. I find it quite elegant when used with pure (as in, non-manhattan) MMD. It doesn't really make sense with manhattan-style, since we can't determine what a level of inheritance is with subtypes. Luke
Multiple colons
Hey grep { !/Luke/ } @Larry, luquimulti foo(Foo, Bar: Baz); # manhattan on Foo and Bar luquimulti foo(Foo: Bar: Baz); # leftmost on Foo and Bar autrijus wtf? autrijus multiple colons? Is that still the case? I don't recall us getting rid of it, but it doesn't seem to be documented in the AES. Maybe I'm just not looking hard enough... Luke
Re: Multiple colons
On Tue, May 17, 2005 at 01:50:48PM +, Luke Palmer wrote: : Hey grep { !/Luke/ } @Larry, : : luquimulti foo(Foo, Bar: Baz); # manhattan on Foo and Bar : luquimulti foo(Foo: Bar: Baz); # leftmost on Foo and Bar : autrijus wtf? : autrijus multiple colons? : : Is that still the case? I don't recall us getting rid of it, but it : doesn't seem to be documented in the AES. We didn't get rid of it. : Maybe I'm just not looking hard enough... Maybe we didn't document it hard enough... But we have at times mentioned various tiebreaking situations. multi methods (as opposed to multi subs) are one instance, where single dispatch to the class is followed by multiple dispatch within the class, so it's equivalent to an extra colon. We've also talked about the possibility of using return type for final tiebreaking. I suppose one could even install a colon on the end of the return type to request that explicitly. Larry
Re: Multiple colons
On Tue, May 17, 2005 at 07:00:23AM -0700, Larry Wall wrote: On Tue, May 17, 2005 at 01:50:48PM +, Luke Palmer wrote: : Is that still the case? I don't recall us getting rid of it, but it : doesn't seem to be documented in the AES. We didn't get rid of it. So does it mean that a 3-story multisub with two colons will always win against one with one colon? multi sub foo (Any $x: Str $y: Str $z, Str $w) { 1 } multi sub foo (Str $x, Str $y: Str $z, Str $w) { 2 } say foo(x, y, z, w); # 1 Is the final level ($z and $w) participating in the MMD at all as tiebreakers? Luke mentioned that in all levels but the final one, Manhattan distance (sum of inheritance deltas of each invs to the expected types) is used, but on the final level, leftmost tiebreaking is used. Is that the case? If yes, why? :) Thanks, /Autrijus/ pgpOwtC66i1df.pgp Description: PGP signature
Re: Quick question: '1.28' * '2.56'
Autrijus Tang wrote: Imagine: pugs '1.28' * '2.56' 3.2768 What is (or should be) going on here here? My personal favorite is [5] none of the above -- that should be a type error. ;) But only if MMD doesn't find a unique handler. That is I would favor 'type error' =:= 'no handler || ambiguous handlers' where ambiguous means most specific with respect to all parameters and not Manhattan distance. But again: mind the sig ;) I further think that infix:* is either simply implemented for :(Any,Any) and relies on prefix:+ to retrieve the numerical value of both operands, or it is overloaded for one( :(Str,Str), all( :(Str,Str), :(Num,Num), :(Str|Num,Str|Num) ) ). The last :() in the all might be surprising, but it is needed to avoid 1.28 * '2.56' beeing ambiguous in symmetrical MMD. Good style would be to let homogenous overloads infix:*:(::X,::X) return ::X to keep the semantics of '*' as multiplication in a type as set interpretation. Actually letting infix:*:(Any,Any) return a Num might force all more specific multis to return at most Num or produce type errors. All that said, and under the assumption that the types of literals are known at compile time, I'm basically opting for a modified [2]: multi sub infix:* (Str $x, Str $y) returns Str { ... } which might be an optimized version that uses lowlevel types and doesn't dispatch two times to prefix:+. But the language semantics can be achieved with infix*:(Any,Any -- Any). Note, that this -- is not part of the current syntax but type theorists will find it very intuitive. pugs '1.28' * '2.56' '3.2768' -- $TSa == all( none( @Larry ), one( @p6l ))
Re: Multiple colons
On Tue, May 17, 2005 at 10:10:22PM +0800, Autrijus Tang wrote: : On Tue, May 17, 2005 at 07:00:23AM -0700, Larry Wall wrote: : On Tue, May 17, 2005 at 01:50:48PM +, Luke Palmer wrote: : : Is that still the case? I don't recall us getting rid of it, but it : : doesn't seem to be documented in the AES. : : We didn't get rid of it. : : So does it mean that a 3-story multisub with two colons will : always win against one with one colon? : : multi sub foo (Any $x: Str $y: Str $z, Str $w) { 1 } : multi sub foo (Str $x, Str $y: Str $z, Str $w) { 2 } : : say foo(x, y, z, w); # 1 It does seem that the signature that provides more information should be rewarded for that somehow. Maybe it's most useful if non-invocant args (or non-invocant-YET args, in this case) are just considered to be at Any distance when matched against real invocants. But we also have to consider that any violated hard constraint anywhere in the signature can disqualify the entrant entirely. : Is the final level ($z and $w) participating in the MMD at all : as tiebreakers? Luke mentioned that in all levels but the final : one, Manhattan distance (sum of inheritance deltas of each invs : to the expected types) is used, but on the final level, leftmost : tiebreaking is used. Is that the case? If yes, why? :) I don't recall ever saying anything like that, so that part of it is presumably speculative on Luke's part. I can't say I like it. Larry
Re: Multiple colons
On 5/17/05, Larry Wall [EMAIL PROTECTED] wrote: On Tue, May 17, 2005 at 10:10:22PM +0800, Autrijus Tang wrote: : Is the final level ($z and $w) participating in the MMD at all : as tiebreakers? Luke mentioned that in all levels but the final : one, Manhattan distance (sum of inheritance deltas of each invs : to the expected types) is used, but on the final level, leftmost : tiebreaking is used. Is that the case? If yes, why? :) I don't recall ever saying anything like that, so that part of it is presumably speculative on Luke's part. I can't say I like it. Just for the folks not following along on IRC, I don't think I implied that. But Autrijus apparently inferred it :-). Anyway, there is no MMD whatsoever on the final level, so that: multi sub foo(Foo: Bar: Baz) {...} multi sub foo(Foo: Bar: Quux) {...} # illegal redefinition Luke
Re: Multiple colons
Autrijus Tang wrote: So does it mean that a 3-story multisub with two colons will always win against one with one colon? multi sub foo (Any $x: Str $y: Str $z, Str $w) { 1 } multi sub foo (Str $x, Str $y: Str $z, Str $w) { 2 } say foo(x, y, z, w); # 1 Is the final level ($z and $w) participating in the MMD at all as tiebreakers? Luke mentioned that in all levels but the final one, Manhattan distance (sum of inheritance deltas of each invs to the expected types) is used, but on the final level, leftmost tiebreaking is used. Is that the case? If yes, why? :) I'm also very keen on hearing the rationale behind these decisions. Do I get it right that Luke is advocating something else in @Larry? If yes, what? I think the only difference apart from scoping issues between a multi method and a multi sub is that the former has the first parameter to be most specific on the class it is defined in. Question: is this parameter always implicitly added or is the double-colon syntax needed to give an explicit invocant identifier? And how does that work together with the ./method syntax? My concern is that all these tie breakers, special casing syntax etc. are weakening the type system. Or putting it differently: How is 'type error' defined? Note that I'm *not* asking at what time it is detected---but it should be before the call or immediatly after when the return type doesn't match the callers wants. -- $TSa == all( none( @Larry ), one( @p6l ))
multi sub and invocants (related to colon question from earlier)
There's some ambiguity in A/S 6 that I wanted to ask about. A6 says: Ordinary subs never have an invocant. If you want to declare a non-method subroutine that behaves as a method, you should declare a submethod instead. But S6 changes that without fully explaining itself: Multimethod and multisub invocants are specified at the start of the parameter list, with a colon terminating the list of invocants S12 sayeth: Ordinarily all the arguments of a multi sub are considered invocants [...] The caller indicates whether to use single dispatch or multiple dispatch by the call syntax. The dot form and the indirect object form default to single dispatch. Subroutine calls with multiple arguments and operators with multiple operands default to multiple dispatch. Ok, so here we are. I'm told on #perl6 that you can't have something like: class Num { method abs() returns Num { ... } } multi sub abs(Num $i:) returns Num { ... } because you're not allowed to define both multi and single-dispatch methods on a class. Let's say that that's true. You can certainly still end up in conflict: class A {...} my A $a = A.new() but role { method x() {...} } eval 'multi sub x(A $i:) {...}'; Now, the eval should work because A has no x method, but you do now have a $a which will conflict on $a.x According to the above bit from S12, $a.x calls single dispatch first, so it should call the anonymous role's method x, right? If I wanted to call the multi, I could aways say: x($a), couldn't I? -- Aaron Sherman [EMAIL PROTECTED] Senior Systems Engineer and Toolsmith It's the sound of a satellite saying, 'get me down!' -Shriekback
Re: multi sub and invocants (related to colon question from earlier)
On 5/17/05, Aaron Sherman [EMAIL PROTECTED] wrote: Let's say that that's true. You can certainly still end up in conflict: class A {...} my A $a = A.new() but role { method x() {...} } eval 'multi sub x(A $i:) {...}'; Now, the eval should work because A has no x method, but you do now have a $a which will conflict on $a.x Well, the way I see it is like so: class A {...} class A_anonymous_role is A { method x() {...} } my A $a = A_anonymous_role.new; eval 'multi sub x(A $i:)'; And that the method gets called because it's more specific than the multi. But that's assuming the transformation: class A { method x() {...} } To: multi sub x(A $self:) {...} Which could be wrong. I think I have pretty good cause to infer that, though. Luke
Closures and CALLER
Is it a bad sign that I'm still on the first section of S29, getting up to speed? Sigh... I'll get there, really. This is another question from my reading this morning. Ok, so log and log10: multi sub Math::Basic::log (: Num ?$x = $CALLER::_, Num +$base); log10 := log.assuming:base(10); What does log get in this case: for @x { log10(); } Does the curried log10 execute the defaulting for the sub it's based on (and thus need run-time access to the default value, which I assume is not in the signature) or does it leave defaulting up to log, in which case, how does log find the right $_? -- Aaron Sherman [EMAIL PROTECTED] Senior Systems Engineer and Toolsmith It's the sound of a satellite saying, 'get me down!' -Shriekback
Re: Quick question: '1.28' * '2.56'
On Tue, May 17, 2005 at 09:04:19PM +0800, Autrijus Tang wrote: : Imagine: : : pugs '1.28' * '2.56' : 3.2768 : : What is (or should be) going on here here? : : [1] role NumRole { : method infix:* returns Num (NumRole $x, NumRole $y: ) { ... } : } : Str.does(NumRole); : : [2] multi sub infix:* (Str $x, Str $y) returns Num { ... } : : [3] multi sub prefix:+ (Str $x) returns Num { ... } : multi sub infix:* (Num $x, Num $y) returns Num { ... } : multi sub infix:* (Any $x, Any $y) returns Num { +$x * +$y } : : [4] multi sub infix:* (Num $x, Num $y) returns Num { +$x * +$y } : # ...and the MMD dispatcher forces incompatible type into : # the type with shared ancestors and closest distance... : : [5] none of the above -- that should be a type error. ;) : : [6] something else? I tend to think of it most like [3], but it's possible that it's the same as [1] if the role is supplying the coercion assumed in [3]. Larry
Re: Closures and CALLER
Aaron Sherman wrote: Ok, so log and log10: multi sub Math::Basic::log (: Num ?$x = $CALLER::_, Num +$base); log10 := log.assuming:base(10); What does log get in this case: for @x { log10(); } Does the curried log10 execute the defaulting for the sub it's based on (and thus need run-time access to the default value, which I assume is not in the signature) or does it leave defaulting up to log, in which case, how does log find the right $_? I had assumed that wrapper a curries function generates does not alter who the CALLER is. Therefore, when log10() is called, the CALLER for log() is the same as the CALLER for log10. IMO, if this is not the case, it severely limits the utility of curried functions. Comments from @Larry requested. -- Rod Adams
Re: Nested captures
On Mon, 09 May 2005 22:51:53 +1000, Damian Conway wrote: # Perl 6... # $1 $2$3 $4$5 $6 $tune_up6 = rx/ (don't) (ray) (me) (for) (solar tea), (d'oh!) # $1 $2 $3$4$5 | (every) (green) (BEM) (devours) (faces) /; Does numbering of captures after an alternation continue as if the alternative with the most captures matched? # $1$1 $2$3, even if (a) matched rx/ [ (a) | (b) (c) ] (d) /; If you explicitly number the first capture in one alternative, does that affect the numbering of the other alternatives? # $4$4 rx/ [ $4:=(a) | (b) ] /; Note that, outside a rule, C@1 is simply a shorthand for C@{$1} Is @/ also a shorthand for @{$/} ? -- Peter Haworth [EMAIL PROTECTED] I am continually amazed by the intuitive straightforwardness of the interface of my microwave and oven. If they were designed by the people who design computer interfaces, it would take both hands and several minutes just to set the timer.-- Adam Rice
Re: Multiple colons
On Tue, May 17, 2005 at 07:26:54AM -0700, Larry Wall wrote: It does seem that the signature that provides more information should be rewarded for that somehow. Maybe it's most useful if non-invocant args (or non-invocant-YET args, in this case) are just considered to be at Any distance when matched against real invocants. But we also have to consider that any violated hard constraint anywhere in the signature can disqualify the entrant entirely. So, if neither Num.does(Str) nor Str.does(Num), is passing a string into multi sub foo (Num $x) { ... } considered a violation on the hard constraint? If yes, I'd like to know if something like this should be the case ([1]): Num is a class, and NumRole supplying a minimal definition of prefix:+ or it's like this instead ([3]): Num is a role, and has a minimal interface of: infix:+ infix:* abs sign and one of: prefix:- infix:- etc. I think the former is simpler (always use coercion), but the latter makes it possible to define various other things that, although not isomorphic with builtin numbers, can still use arithmetic operators. Thanks, /Autrijus/ pgpvJ0CD0eTFk.pgp Description: PGP signature
Re: Nested captures
On 2005-05-17 14:14, Peter Haworth [EMAIL PROTECTED] wrote:\ Does numbering of captures after an alternation continue as if the alternative with the most captures matched? # $1$1 $2$3, even if (a) matched rx/ [ (a) | (b) (c) ] (d) /; I thought that was still like Perl5: # $1$2 $3$4 rx/ [ (a) | (b) (c) ] (d) /; The *numbering* is based on the regex; the *values* are based on the actual match. What's changed in the Perl6 design, AIUI, is nested captures. Given this: rx/ (a (b (c d) e) f) / In Perl5, $1 is abcdef, $2 is bcde, and $3 is cd. In the proposed Perl6 model, there is no $2, just $1 (an object which stringifies to abcdef, $1.1 (an object which stringifies to bcde), and $1.1.1 (an object which stringifies to cd. If you explicitly number the first capture in one alternative, does that affect the numbering of the other alternatives? # $4$4 rx/ [ $4:=(a) | (b) ] /; Note that, outside a rule, C@1 is simply a shorthand for C@{$1} Is @/ also a shorthand for @{$/} ?
Re: Multiple colons
On Tue, May 17, 2005 at 02:45:58PM +, Luke Palmer wrote: Just for the folks not following along on IRC, I don't think I implied that. But Autrijus apparently inferred it :-). My apologies. It's a misparse on my part. Anyway, there is no MMD whatsoever on the final level, so that: multi sub foo(Foo: Bar: Baz) {...} multi sub foo(Foo: Bar: Quux) {...} # illegal redefinition Hmm. How does this play with Larry's suggestion: I suppose one could even install a colon on the end of the return type to request that explicitly. Does it mean that: multi sub foo(Foo: Bar: Baz:) returns Boo {...} multi sub foo(Foo: Bar: Baz:) returns Foo {...} would MMD on the return type, but still ignore the Baz for MMD? Thanks, /Autrijus/ pgpSWytLLuVDk.pgp Description: PGP signature
Re: Nested captures
On Tue, May 17, 2005 at 03:02:12PM -0400, Mark Reed wrote: On 2005-05-17 14:14, Peter Haworth [EMAIL PROTECTED] wrote:\ Does numbering of captures after an alternation continue as if the alternative with the most captures matched? # $1$1 $2$3, even if (a) matched rx/ [ (a) | (b) (c) ] (d) /; I thought that was still like Perl5: # $1$2 $3$4 rx/ [ (a) | (b) (c) ] (d) /; The *numbering* is based on the regex; the *values* are based on the actual match. Nope. See the section entitled Subpattern numbering in http://groups-beta.google.com/group/perl.perl6.language/msg/2a4b1117301c62b4?hl=en To quote: Specifically, there are significant advantages to numbering the subpatterns in each branch of an alternation (i.e. oneither side of a C|) independently, restarting the numbering at the beginning of each branch. And this is precisely what Perl 6 does: # Perl 6... # $1 $2$3 $4$5 $6 $tune_up6 = rx/ (don't) (ray) (me) (for) (solar tea), (d'oh!) # $1 $2 $3$4$5 | (every) (green) (BEM) (devours) (faces) /; In other words, unlike in Perl 5, in Perl 6 $1 doesn't represent the capture made by the first subpattern that appears in the rule; it represents the capture made by the first subpattern of whichever alternative actually matched. Although last I heard, Larry had agreed to make the first captured paren be $0 rather than $1 so that it could correspond to the indexing of the match object when used as an array. What's changed in the Perl6 design, AIUI, is nested captures. Given this: rx/ (a (b (c d) e) f) / In Perl5, $1 is abcdef, $2 is bcde, and $3 is cd. In the proposed Perl6 model, there is no $2, just $1 (an object which stringifies to abcdef, $1.1 (an object which stringifies to bcde), and $1.1.1 (an object which stringifies to cd. Yep. Assuming the $1.1 syntax works. -Scott -- Jonathan Scott Duff [EMAIL PROTECTED]
Re: Multiple colons
On Wed, May 18, 2005 at 04:02:16AM +0800, Autrijus Tang wrote: : Hmm. How does this play with Larry's suggestion: : : I suppose one could even install a colon on the end of the return : type to request that explicitly. : : Does it mean that: : : multi sub foo(Foo: Bar: Baz:) returns Boo {...} : multi sub foo(Foo: Bar: Baz:) returns Foo {...} : : would MMD on the return type, but still ignore the Baz for MMD? No, I meant: multi sub foo(Foo: Bar: Baz) returns Boo: {...} multi sub foo(Foo: Bar: Baz) returns Foo: {...} But that's a bit strange, and in any event it's problematical to depend on a context that might not be known till after we call foo() anyway, unless even the dispatch to foo() is done lazily. Larry
Re: Closures and CALLER
On Tue, May 17, 2005 at 01:01:48PM -0500, Rod Adams wrote: : Aaron Sherman wrote: : : Ok, so log and log10: : : multi sub Math::Basic::log (: Num ?$x = $CALLER::_, Num +$base); : log10 := log.assuming:base(10); : : What does log get in this case: : : for @x { : log10(); : } : : Does the curried log10 execute the defaulting for the sub it's based on : (and thus need run-time access to the default value, which I assume is : not in the signature) or does it leave defaulting up to log, in which : case, how does log find the right $_? : : : I had assumed that wrapper a curries function generates does not alter : who the CALLER is. Therefore, when log10() is called, the CALLER for : log() is the same as the CALLER for log10. : : IMO, if this is not the case, it severely limits the utility of curried : functions. Comments from @Larry requested. Makes sense to me. I don't think .assuming should assume anything that is not explicitly specified as assumed, so defaults should not resolve till the real call. Larry
Re: Quick question: '1.28' * '2.56'
Rob Kinyon wrote: If that's the case, then if I change a variable that isa Str (that isa Num), does it change what it inherits from? Please don't use inherits when talking about these core types. Classical inheritance just doesn't work with the varied sets of numbers. All those stories you were told about Classical Inheritance being able to describe any problem were naïve lies. Roles-based inheritance (or Traits-based if you like Smalltalk, or Haskell's Classes) is a superset of classical inheritance. In fact it seems reasonable to me at this point in time that a Perl 6 Class is a subtype of a Role. The distinctions seem minor enough not to matter. See also http://svn.openfoundry.org/pugs/docs/src/number-types.png Sam.
Re: Quick question: '1.28' * '2.56'
Larry Wall wrote: : pugs '1.28' * '2.56' : 3.2768 : What is (or should be) going on here here? : [1] role NumRole { : method infix:* returns Num (NumRole $x, NumRole $y: ) { ... } : } : Str.does(NumRole); : [3] multi sub prefix:+ (Str $x) returns Num { ... } : multi sub infix:* (Num $x, Num $y) returns Num { ... } : multi sub infix:* (Any $x, Any $y) returns Num { +$x * +$y } I tend to think of it most like [3], but it's possible that it's the same as [1] if the role is supplying the coercion assumed in [3]. I like #3, because it doesn't have any nasty implications to the type calculus. I don't really have the theoretical or practical knowledge to really be able to back this up, but I have a strong hunch that value-based type shifting is the type system equivalent of $. Sam.