Поддерживает ли Perl6 зависимые типы?

Недавно я смотрел страницу wikipedia для зависимых типов, и мне было интересно; действительно ли Perl 6 действительно вводит зависимые типы? Я не могу найти надежного источника, утверждающего, что.

Для некоторых это может быть очевидно, но я уверен, что черт не очевиден для меня.

Ответ 1

Против Ven, в комментариях, следующих за ответом Perl 6 на вопрос SO "Есть ли язык с ограниченными типами?", написал "perl6 doesn 't имеют зависимые типы" и позже написал "зависимый тип, возможно, нет,... ну, если мы получим разрешимый where s..." в обмене на # perl6. (Реакция Ларри Уолла была "какие проблемы с остановкой среди друзей" . Кстати, лучший способ получить авторитетный ответ на все вопросы Perl 6 должен запросить TimToady через # perl6.)

Для Резюме для тега SOA зависимого типа:" Зависимые типы - это типы, зависящие от значений". Perl 6 поддерживает типы, зависящие от значений, поэтому есть.

Для Резюме редактирования для изменения Awwaiid, которое добавило Perl 6 на страницу Википедии на Dependent Types "Perl 6... имеет неразрешимые зависимые типы".

Страница Википедии начинается с:

зависимый тип - это тип, определение которого зависит от значения. "Пара целых чисел" - это тип. "Пара целых чисел, где вторая больше первой" является зависимым типом из-за зависимости от значения.

Здесь один из способов создания типа по этим строкам в 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

Означает ли это, что функция Perl 6 subset генерирует зависимые типы? Возможно, это то, о чем думает авваид.

Ответ 2

Возможно, да, поскольку подмножества являются типами, которые могут зависеть от произвольных условий. Однако система типов будет классифицирована как несостоятельная, поскольку инварианты типа не применяются.

В частности, ограничение типа переменной проверяется только при назначении, поэтому модификации объекта, которые заставляют его удаляться из подмножества, приведут к переменной, содержащей объект, который он не сможет, например

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

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

Вы можете использовать какое-либо метаобъектное волшебство, чтобы система объекта автоматически проверяла тип после любого вызова метода, боксируя объекты в прозрачных защитных объектах.

Наивная реализация может выглядеть так:

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'));
}

Это приведет к сбою:

my $guarded-list = guard([1, 2, 3], OrderedList);
$guarded-list[0] = 42;