13

I was recently looking at the wikipedia page for dependent types, and I was wondering; does Perl 6 actually introduce dependent types? I can't seem to find a reliable source claiming that.

It might be obvious to some, but it sure as heck ain't obvious to me.

Pat
  • 36,282
  • 18
  • 72
  • 87
hao ramirez
  • 235
  • 1
  • 6

2 Answers2

12

Against Ven, in the comments following the Perl 6 answer to the SO question "Is there a language with constrainable types?", wrote "perl6 doesn't have dependant types" and later wrote "dependent type, probably not, ... well, if we get decidable wheres..." in an exchange on #perl6. (Larry Wall's response was "what's a few halting problems among friends". Btw, by far the best way to get an authoritative answer on all things Perl 6 is to ask TimToady via #perl6.)

For The summary for the 'dependent-type' SO tag is "Dependent types are types that depend on values." Perl 6 supports types that depend on values, so there's that.

For The edit summary for the change by Awwaiid that added Perl 6 to Wikipedia's page on Dependent Types says "Perl 6 ... has undecidable dependent types".

The Wikipedia page starts with:

a dependent type is a type whose definition depends on a value. A "pair of integers" is a type. A "pair of integers where the second is greater than the first" is a dependent type because of the dependence on the value.

Here's one way to create a type along those lines in Perl 6:

subset LessMorePair of Pair where { $_.key < $_.value }
subset MoreLessPair of Pair where { $_.key > $_.value }

multi sub foo (        Pair) { "  P" }
multi sub foo (LessMorePair) { "LMP" }
multi sub foo (MoreLessPair) { "MLP" }

for 1 => 1, 1 => 2, 2 => 1 { say foo $_ }

#   P
# LMP
# MLP

Does this mean the Perl 6 subset feature generates dependent types? Perhaps this is what Awwaiid is thinking of.

Community
  • 1
  • 1
raiph
  • 31,607
  • 3
  • 62
  • 111
  • 1
    Well, in the sense that perl 6 has "types depending on values", then yes sure. By this definition, C also does. But only having indexed types isn't very useful in itself. – Ven Jul 31 '17 at 06:38
  • 1
    FWIW, [I also considered hijacking parameterized roles](https://github.com/vendethiel/6meta-experiments/blob/master/church.pl), but only the `count` version works (which unties them at runtime). Roles would need an "instantiation" phase (like C++ templates) to get something akin to dependent types, but that's not on the menu :-). – Ven Jul 31 '17 at 06:42
11

Arguably yes as subsets are types that may depend on arbitrary conditions. However, the type system would be classified as unsound as type invariants are not enforced.

In particular, a variable's type constraint is only checked on assignment, so modifications to an object that make it drop from a subset will lead to a variable holding an object it should not be able to, eg

subset OrderedList of List where [<=] @$_;

my OrderedList $list = [1, 2, 3];
$list[0] = 42;
say $list ~~ OrderedList;

You can use some meta-object wizardry to make the object system automatically check the type after any method call by boxing objects in transparent guard objects.

A naive implementation could look like this:

class GuardHOW {
    has $.obj;
    has $.guard;
    has %!cache =
        gist => sub (Mu \this) {
            this.DEFINITE
                ?? $!obj.gist
                !! "({ self.name(this) })";
        },
        UNBOX => sub (Mu $) { $!obj };

    method find_method(Mu $, $name) {
        %!cache{$name} //= sub (Mu $, |args) {
            POST $!obj ~~ $!guard;
            $!obj."$name"(|args);
        }
    }

    method name(Mu $) { "Guard[{ $!obj.^name }]" }
    method type_check(Mu $, $type) { $!obj ~~ $type }
}

sub guard($obj, $guard) {
    use nqp;
    PRE $obj ~~ $guard;
    nqp::create(nqp::newtype(GuardHOW.new(:$obj, :$guard), 'P6int'));
}

This will make the following fail:

my $guarded-list = guard([1, 2, 3], OrderedList);
$guarded-list[0] = 42;
Christoph
  • 164,997
  • 36
  • 182
  • 240
  • 1
    I agree with the general sentiment, though a hardcore dependent typist (or whatever advocates for dependent types are called) might object that the type isn't checked at compile time, and so your example doesn't count. I guess it's all up to interpretation. – moritz Jul 24 '17 at 04:08
  • What @moritz said. Runtime is un(i)typed, so it needs to happens at compile-time. – Ven Jul 31 '17 at 06:44