Day 182 (r6110): Wildcard types, type operators, logic progr

autrijus on 2005-08-07T20:34:34

The Perl 6 design team gathered twice today (well, it's two days for them, but one day to me), to form consensus on all sorts of design issues. Chip was kind enough to relay part of the discussion to #perl6. Below are collected from the IRC notes -- none of these is set in stone; they are not official until a fuller writeup is produced and made into p6l/Synopses.

I like the .variants selector:

# &f is a multi sub
multi f (Int $x) {...}
multi f (Num $x) {...}
multi f (Str $x) {...}

# &g is also multi sub, with Int and Num forms
my &g := &f.variants(Int);

# &h is now a single sub
my &h := &g.variants(Num);
This replaces the old ugly &f:(Int) syntax.

I brought up a couple type-theoretical issues that's crucial to full type inferencing, and received satisfactory solutions. In particular, the arrow type operator is borrowed from ML/Haskell. The two forms below are equivalent:

my sub negate (Num $x --> Num) { ... }
my Num sub negate (Num $x) { ... }
The return type then follows the full inferencing rules. That is, the inner return() will only accept Num or its subtype (eg. Int); the caller to negate needs to accept Num or its supertype (eg. Complex).

However, sometimes the user wants runtime coercion. In that case, the old returns Num form is used. It's not part of the subroutine type, so the caller does not see it. Hence the two forms below are equivalent:

my sub negate (Num $x) returns Num { ... }
my sub negate (Num $x --> Any) returns Num { ... }

The rule of thumb is: If you want compile time typecheck, use the arrow type. If you want runtime (possibly failing) coercion, use is returns.

Attentive reader may note that the Any type above is used in a contravariant position. Indeed, that's the second topic I raised: Any will henceforth act as a wildcard type -- that is, it's both a supertype of any type, and the subtype of any type. In the words of chip:

 hey, neat: Any is shorthand for any(@all_types)
 yeah. that's what it means :)
 "I love it when a plan comes together."

The overloading of junctive value operators to mean intersectional type operators has been controversial for quite some time. luqui proposed another set of Set operators, written as (+) (union), (-) (difference), (*) (intersection). Hence, we can write (Num (-) Int) to mean nonintegral numbers. They also have unicode renderings, like (Num ⊖ Int ⊕ Animal ⊘ Red).

To compare set member equality and Hash keys for unrestricted key types, we need a generic identity tester for objects (comparing their .id) and values (comparing their type and presentation). Because =:= is taken to test container bindings, it looks like infix eqv is getting introduced to test generic equivalence.

Inspired by Ovid's journal, I've been learning Curry, a Haskell descendent that adds logic programming (i.e. Prolog). Taking Curry's treatment of free variables (let x free in ...) and assertions (succ x =:= succ y), and luqui's suggestion of a ` twigil to mean free variables, I produced this pseudocode for discussion:

multi append ([], @ys) { @ys }
multi append ([*$x, *@xs], @ys) {
    ($xs, append @xs, @ys)
}
sub last (@l) {
    my ($`x, @`xs);
    append(@`xs, [$`x]) === @l;
    $`x;
}
Note how the language solves $`x all by itself. It's just blue-sky talk at this moment -- no-one thinks we should delay Perl 6 any further to chase logic programming. However, it's good to think about the semantics and how it may be supported by a future version or extension modules.

In other news:

  • putter posted a half-finished patch to pave the way to write a Rules engine in Perl 6.
  • iblech added Junction support for the Javascript backend.
  • brentdax discovered a degenerate case in parser that looks like the cause of quite a few exponential slowdowns.
  • putter did a heroic undertaking in reviving hundreds of PGE tests to the main t/ tree, verifying it with PGE from 0.2.3. Now pmichaud should have plenty of failing tests to motivate his PGE hacking...
  • Stevan starts aligning the Perl 5 edition of object metamodel to the non-nominal treatment adopted by Haskell and Javascript backends, and produced a CPAN module, Class::C3, to expose the new C3 dispatch order to regular Perl5 programs.
  • fglock fulfilled his promise and produced Array-Lazy, the prototype for proper generators and iterators support.
There's much more to write (and backlog), but I need to wake up in 5 hours for $work, so I'd better stop now...