2017-02-08 18 views
2

Я читал на зависимых типах, и у меня есть один вопрос, чтобы убедиться, что я не что-то недопонимаю. Wikipedia page on dependent types:Являются ли дженерики параметризуемыми значениями такими же, как и зависимые типы?

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


Предположим, что у меня есть язык, где я могу представлять собой число в диапазоне:

struct Int<Min, Max> 

Например, тип Int<0, 10> представляет собой целое число от 0 включительно и 10 эксклюзивных.

В качестве бонуса, предположим, я представлю общую дисперсию:

struct Int<in Min, out Max> 

Например, экземпляры типов, таких как Int<3, 10> и Int<0, 8> могут быть назначены на переменные типа Int<0, 10>.

Теперь операция сложения по этому типу может иметь подпись, как это:

Int<Min1 + Min2, Max1 + Max2> operator+(Int<Min1, Max1> op1, Int<Min2, Max2> op2); 

Таким образом, добавление Int<0, 10> и бы получить результат типа Int<3, 14>.

В такой системе типа, мы могли бы также упорядоченные пары, такие как:

struct OrderedPair<Min, Mid, Max> 
{ 
    Int<Min, Mid> SmallerNumber; 
    Int<Mid, Max> LargerNumber; 
} 

и так далее.


Это отличается от зависимой печати? Если да, то как?

+0

Зависимый тип позволяет прикрепить предикат к типу и проверить, что он выполняется во всех операциях. Если вы можете ограничить свою систему несколькими предикатами (например, min/max для диапазона), вы можете разгрузить его, чтобы ввести параметры в степень; Хаскелл вроде как позволяет это сделать, я слышал. То есть для практического случая чисел в пределах диапазона или списков не более N элементов вы, вероятно, можете это достичь.В общем случае, скорее всего, нет, иначе зачем людям изобретать языки, отпечатанные на разных языках? – 9000

+1

@ 9000 Да, я в основном пытаюсь понять, могут ли определенные типы (такие как «Int », возможный «Список », а также несколько других), могут в основном использоваться в качестве строительных блоков для достижения целого тип системы зависимых типов или система зависимого типа - это нечто совсем другое. –

ответ

3

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

В полностью зависимом набранном языке, таком как Idris, типы также могут зависеть от значений времени выполнения. Чтобы построить такое значение, вам понадобится proof в объеме, в котором значение имеет тип. Один из способов получить доказательство является простым испытанием (псевдокод):

m = user_input(); 
n = user_input(); 

// Type error: n is not guaranteed to be in range. 
x = Int<0, m>(n); 

if (n >= 0 && n <= m) { 
    // Accepted: proofs of n >= 0 and n <= m in scope. 
    x = Int<0, m>(n); 
} 

Таким образом, вы можете реализовать свой пример (скажем) C++, но построения Int<Min, Max> требует динамической проверки в конструкторе; если C++ имел полные зависимые типы, вы не могли бы даже вызвать конструктор без какой-либо проверки (статический или динамический).

+0

Часть вопроса о доказательстве, требующемся для создания экземпляров, имеет смысл для меня. Однако в этом коде 'm' является значением времени выполнения. Дело не только в том, что мы перешли от 'n' (неограниченный' int ', предположительно) к 'Int <0, m>', той части, которую я понимаю. Но 'Int <0, m>' содержит значение, которое не известно статически. Может ли закрывающая функция вернуть 'x'? Может ли тип закрывающей функции быть 'Int <0, m>'? Если это так, когда я пытаюсь назначить 'Int <0, m>' '' Int <0, 5> ', как компилятор узнает, если я перейду к более или менее конкретному типу? –

+0

Тип 'x' в этом if-statement равен' Int <0, m> ', но тип закрывающей функции не может быть таким, потому что неизвестно (не может быть доказано), что значения времени выполнения передадут это if-check , Однако, если у вас есть else-предложение, которое возвращает '0' (или' m'), то вы можете получить, что тип возвращаемого значения всего объекта - 'Int <0, m>'. – laughedelic

+0

@ TheodorosChatzigiannakis: Я думаю, вы могли бы вернуть значение, обернув его экзистенциальным, '∃m. Int <0, m> ', то вызывающий может распаковать его для работы со значением' m' локально. То есть, функция говорит: «Я возвращаю значение в диапазоне [0, * m *] для некоторого * m *". Экзистенциальный тип называется «зависимой парой» или «сигма-типом» в этом контексте, потому что это пара значений 'm' и тип' Int <0, m> ', который зависит от него. –