Подтвердить что ты не робот

Является ли система С# звуковой и разрешимой?

Я знаю, что система типа Java является необоснованной (он не может вводить проверки, которые являются семантически законными) и неразрешимым (он не может ввести проверку некоторой конструкции).

Например, если вы скопируете/вставьте следующий фрагмент в класс и скомпилируете его, компилятор сработает с StackOverflowException (как apt). Это неразрешимость.

static class ListX<T> {}
static class C<P> extends ListX<ListX<? super C<C<P>>>> {}
ListX<? super C<Byte>> crash = new C<Byte>();

Java использует подстановочные знаки с ограничениями типов, которые являются формой дисперсии использования сайта. С#, с другой стороны, использует аннотацию вариации сайта объявления (с ключевыми словами in и out). Известно, что дисперсия объявления-сайта слабее, чем дисперсия на сайте-участнике (вариация на сайте-участнике может выражать все отклонения от объявлений-сайтов, а более - в нижней части, это гораздо более подробный).

Итак, мой вопрос: Является ли система С# звуковой и разрешимой? Если нет, то почему?

4b9b3361

Ответ 1

Является ли система С# звуковой и разрешимой?

Это зависит от того, какие ограничения вы вводите в систему типов. Некоторые разработчики систем типа С# имеют документ по этой теме, который, вероятно, найдет интересным:

https://www.microsoft.com/en-us/research/publication/on-decidability-of-nominal-subtyping-with-variance/

На практике компиляторы С# 4.0 и 5.0 не используют детектор бесконечного типа, описанный в документе; скорее, они идут в неограниченную рекурсию и крушение.

Я подумал о добавлении такого кода в Roslyn, но не помню, на этот раз он попал или нет; Я проверю исходный код, когда вернусь в свой офис на следующей неделе.

Более легкое введение в проблему можно найти в моей статье здесь:

http://blogs.msdn.com/b/ericlippert/archive/2008/05/07/covariance-and-contravariance-part-twelve-to-infinity-but-not-beyond.aspx

ОБНОВЛЕНИЕ: Вопрос, заданный Андреем в оригинальной статье, - это проверка конвертируемости в мире с номинальным подтипированием и контравариантными генериками, которые обычно разрешимы? - недавно был дан ответ. Это не. См. https://arxiv.org/abs/1605.05274. Я рад отметить, что автор заметил один из моих сообщений по этому вопросу - не этот - и был вдохновлен атаковать проблему.

Ответ 2

Не так сложно создавать проблемы, которые С# complier не может решить за разумное время. Некоторые проблемы, с которыми он сталкивается (часто связанные с выводом типа дженериков/типов), являются NP-трудными проблемами. Эрик Липперт описывает один такой пример здесь:

class MainClass
{
    class T{}
    class F{}
    delegate void DT(T t);
    delegate void DF(F f);
    static void M(DT dt)
    {
        System.Console.WriteLine("true");
        dt(new T());
    }
    static void M(DF df)
    {
        System.Console.WriteLine("false");
        df(new F());
    }
    static T Or(T a1, T a2, T a3){return new T();}
    static T Or(T a1, T a2, F a3){return new T();}
    static T Or(T a1, F a2, T a3){return new T();}
    static T Or(T a1, F a2, F a3){return new T();}
    static T Or(F a1, T a2, T a3){return new T();}
    static T Or(F a1, T a2, F a3){return new T();}
    static T Or(F a1, F a2, T a3){return new T();}
    static F Or(F a1, F a2, F a3){return new F();}
    static T And(T a1, T a2){return new T();}
    static F And(T a1, F a2){return new F();}
    static F And(F a1, T a2){return new F();}
    static F And(F a1, F a2){return new F();}
    static F Not(T a){return new F();}
    static T Not(F a){return new T();}
    static void MustBeT(T t){}
    static void Main()
    {
        // Introduce enough variables and then encode any Boolean predicate:
        // eg, here we encode (!x3) & ((!x1) & ((x1 | x2 | x1) & (x2 | x3 | x2)))
        M(x1=>M(x2=>M(x3=>MustBeT(
          And(
            Not(x3), 
            And(
              Not(x1), 
              And(
                Or(x1, x2, x1), 
                Or(x2, x3, x2))))))));
    }
}