РЕДАКТИРОВАТЬ: комментарий выше предоставил недостающую часть. Некоторые люди преднамеренно играют с языками, не требующими полного обучения. Мне явно наплевать на такие языки. Действительно полезный не полный по языку язык - безумно сложная вещь для разработки. Все остальное расширяется на том, что происходит, пытаясь применить эти теоремы к полному языку.
Ложь!
function f(a): forall t: Type, t->t
function g(a): forall t: Type, t->t
return (a is g) ? f : a
return a is f ? g : a
где is
оператор сравнивает две переменные для ссылочной идентичности. То есть они содержат одинаковое значение. Не эквивалентное значение, то же значение. Функции f
и g
эквивалентны по определению, но они не совпадают.
Если эта функция передается сама, она возвращает что-то еще; в противном случае он возвращает свои данные. Нечто другое имеет тот же тип, что и сам, поэтому его можно заменить. Другими словами, f
это не личность, потому что f(f)
возвращается g
, тогда как личность вернется f
.
Для выполнения теоремы она должна предполагать смешную способность уменьшать
function cantor(n, <z, a>) : forall t: t: Type int, <int, t> -> <int, t>
return n > 1 ? cantor((n % 2 > 0) ? (n + 1) : n / 2, <z + 1, a>) : <z, a>
return cantor(1000, <0, a>)[1]¹
Если вы хотите предположить, что вы можете предположить, что гораздо более простой вывод типа может быть обработан.
Если мы попытаемся ограничить область до тех пор, пока теорема не будет выполнена, мы в конечном итоге вынуждены ограничить ее ужасно далеко.
- Чистый функционал (нет изменяемого состояния, нет ввода-вывода). ОК, я могу жить с этим. Много времени мы хотим запустить доказательства над функциями.
- Пустая стандартная библиотека. Мех.
- Нет
raise
и нет exit
. Теперь мы начинаем ограничиваться.
- Нет нижнего типа.
- В языке есть правило, которое позволяет компилятору свернуть бесконечную рекурсию, предполагая, что она должна завершиться. Компилятору разрешено отклонять тривиальную бесконечную рекурсию.
- Компилятору разрешается сбой, если он представлен чем-то, что не может быть доказано в любом случае. Теперь стандартная библиотека не может принимать функции в качестве аргументов. Бу.
- Существует нет
nil
. Это начинает становиться проблематичным. У нас закончились способы борьбы с 1/0.
- Язык не может делать выводы типа ветви и не имеет переопределения, когда программист может доказать вывод типа, который язык не может. Это довольно плохо.
Существование обоих последних двух ограничений нанесло ущерб языку. Пока Тьюринг еще не завершен, единственный способ получить работу общего назначения - это симулировать внутреннюю платформу, которая интерпретирует язык с более слабыми требованиями.
¹ Если вы думаете, что компилятор может вывести это, попробуйте этот
function fermat(z) : int -> int
function pow(x, p)
return p = 0 ? 1 : x * pow(x, p - 1)
function f2(x, y, z) : int, int, int -> <int, int>
left = pow(x, 5) + pow(y, 5)
right = pow(z, 5)
return left = right
? <x, y>
: pow(x, 5) < right
? f2(x + 1, y, z)
: pow(y, 5) < right
? f2(2, y + 1, z)
: f2(2, 2, z + 1)
return f2(2, 2, z)
function cantor(n, <z, a>) : forall t: t: Type int, <int, t> -> <int, t>
return n > 1 ? cantor((n % 2 > 0) ? (n + 1) : n / 2, <z + 1, a>) : <z, a>
return cantor(fermat(3)[0], <0, a>)[1]
² Доказательство того, что компилятор не может этого сделать, зависит от ослепления. Мы можем использовать несколько библиотек, чтобы компилятор не мог видеть цикл одновременно. Кроме того, мы всегда можем создать что-то, где программа будет работать, но не может быть скомпилирована, потому что компилятор не может выполнить индукцию в доступной памяти.
Кто-то думает, что вы можете получить этот return nil без произвольных обобщенных типов, возвращающих nil. Это платит противное наказание, за которое я не видел ни одного эффективного языка, который мог бы заплатить.
function f(a, b, c): t: Type: t[],int,int->t
return a[b/c]
не должен компилироваться. Основная проблема заключается в том, что индексирование массивов во время выполнения больше не работает.