Что на самом деле должно быть доказательством правильности проверки типов?

11

Я программирую уже несколько лет, но очень незнаком с теоретической CS. Недавно я пытался изучать языки программирования и, как часть этого, проверку типов и вывод.

Мой вопрос заключается в том, что если я пытаюсь написать программу для вывода и проверки типов для языка программирования, и я хочу доказать, что мой тестер типов работает, какое именно доказательство я ищу?

Говоря простым языком, я хочу, чтобы моя программа проверки типов могла выявлять любые ошибки в фрагменте кода, которые могут возникнуть во время выполнения. Если бы я использовал что-то вроде Coq, чтобы попытаться доказать, что моя реализация верна, что именно будет пытаться показать это «доказательство правильности»?

Вивек Гайс
источник
Может быть, вы можете уточнить, хотите ли вы знать (1) реализует ли ваша реализация заданную систему типизации или (2) предотвращает ли ваша система типизации T ошибки, которые, по вашему мнению, должны быть выполнены? Это разные вопросы. TT
Мартин Бергер
1
@MartinBerger: Ах, похоже, я пропустил эту разницу. Мой фактический вопрос, вероятно, хотел задать оба. Контекст заключается в том, что я пытаюсь построить язык, и для этого я писал проверку типов. И люди просили меня использовать проверенный и проверенный алгоритм. Мне было интересно посмотреть, как трудно будет «доказать», что алгоритм и проверка типов, которые я использовал, были «правильными». Отсюда и двусмысленность в моем вопросе.
Вивек Гайсас
2
(1) действительно вопрос проверки программы и имеет мало общего с набором текста. Просто нужно показать, что ваша реализация соответствует его спецификации. Что касается (2), сначала определите, что значит быть немедленной ошибкой типа (например, такие термины 2 + "hello"«застряли»). Как только это будет формализовано, вы можете доказать теорему об устойчивости типа. Это означает, что ни одна типизированная программа не может развиться в немедленную ошибку типа. Формально вы доказываете, что если программа является типизируемой и для любого n : если M выполняет n шагов, чтобы стать N , то у N нет немедленной ошибки типа. (1/2)MnMnNN
Мартин Бергер
1
Это обычно подтверждается индукцией по и выводом печатного текста. (2/2)n
Мартин Бергер
Спасибо! Исходя из вашего объяснения, кажется, что (2) действительно то, что я искал. Не могли бы вы сделать это ответ? (И, возможно, добавьте любые подробности, которые, по вашему мнению, могут быть полезны.) Я бы принял это как ответ! :)
Вивек Гайсас

Ответы:

10

Вопрос можно интерпретировать двумя способами:

  • Реализует ли реализация заданную систему типирования ?T
  • T

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

TT

  • Во-первых, вы формально определяете, что означает для программы немедленное опечатывание . Это можно определить многими способами - решать только вам. Как правило, мы хотим предотвратить такие программы, как 2 + "hello". Другими словами, вам нужно определить подмножество программ, назовите их Bad , которые содержат именно программы с немедленной ошибкой ввода.

  • ΓM:α.MαΓ

    ΓM:αMNN

    Как доказать эту теорему, зависит от деталей языка, системы набора текста и вашего выбора Bad .

MMNM

  • ΓM:αMNΓN:α

  • ΓM:αM

Обратите внимание, что не во всех системах ввода текста есть «сокращение предмета», например, типы сеансов. В этом случае требуются более сложные методы доказательства.

Мартин Бергер
источник
20

Это хороший вопрос! Он спрашивает, что мы ожидаем от типов в типизированном языке.

Во-первых, обратите внимание, что мы можем напечатать любой язык программирования с Unlepe : просто выберите букву, скажем U, и скажите, что у каждой программы есть тип U. Это не очень полезно, но это важно.

eAeAAint

Нет конца тому, насколько выразительными могут быть ваши типы. В принципе, это могут быть любые логические утверждения, они могут использовать теорию категорий и тому подобное и т. Д. Например, зависимые типы позволят вам выражать такие вещи, как «эта функция отображает списки в список таким образом, чтобы выходные данные были отсортированным входным». Вы можете пойти дальше, в данный момент я слушаю доклад о "параллельной логике разделения", которая позволяет вам говорить о том, как параллельные программы работают с общим состоянием. Модные вещи.

Искусство типов в дизайне языка программирования - это искусство сочетания выразительности и простоты :

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

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

Итак, давайте вернемся к вашему вопросу: откуда вы знаете, что ваша система типов хороша ? Ну, докажите теоремы, которые показывают, что ваши типы сбалансированы. Будет два вида теорем:

  1. Теоремы, которые говорят, что ваши типы полезны . Знание того, что программа имеет тип, должно подразумевать некоторые гарантии, например, что программа не застрянет (это будет теорема безопасности ). Другое семейство теорем связывало бы типы с семантическими моделями, чтобы мы могли начать использовать реальную математику для доказательства наших программ (это будут теоремы об адекватности и многие другие). Вышеуказанное единство плохо, потому что у него нет таких полезных теорем.

  2. Теоремы, которые говорят, что ваши типы просты . Основным было бы то, что можно решить, имеет ли данное выражение заданный тип. Еще одна особенность простоты - предоставить алгоритм для вывода типа. Другие теоремы о простоте могут заключаться в том, что выражение имеет не более одного типа или что выражение имеет основной тип (т. Е. «Лучший» среди всех типов, которые оно имеет).

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

Андрей Бауэр
источник
Спасибо за этот подробный ответ! Тем не менее, я все еще не уверен насчет ответа на мой вопрос. В качестве конкретного примера, давайте возьмем C - статически типизированный язык с достаточно простой системой типов. Если бы я написал проверку типов для C, как бы мне доказать, что мой контроль типов является «правильным»? Как этот ответ изменится, если вместо этого я напишу проверку типов для Haskell, скажем, HM? Как бы мне сейчас доказать «правильность»?
Вивек Гайсас
1
TeATeA
Я бы рекомендовал делать 2. и 3. как комбинацию. Кроме того, взгляните на CompCert .
Андрей Бауэр
1
TeAeAe
AAe
5

Есть несколько разных вещей, которые вы могли бы иметь в виду под «доказать, что мой проверщик типов работает». Что, я полагаю, является частью того, что задает ваш вопрос;)

Половина этого вопроса доказывает, что ваша теория типов достаточно хороша, чтобы доказать любые свойства языка. Ответ Андрея очень хорошо справляется с этой задачей. Другая половина вопроса - предположим, что язык и его система типов уже исправлены - как вы можете доказать, что ваша конкретная программа проверки типов действительно правильно реализует систему типов? Есть две основные перспективы, которые я вижу здесь.

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

Вторая перспектива - это более математический взгляд на правильность. При работе с языками в математике мы часто устанавливаем «модели» для наших «теорий» (или наоборот) и затем пытаемся доказать: (а) все, что мы можем сделать в теории, которую мы можем сделать в модели, и (б) все, что мы можем сделать в модели, мы можем сделать в теории. (Это Корректность и полнотатеоремы. Какой из них зависит от того, «исходили ли вы» из синтаксической теории или из семантической модели.) При таком мышлении мы можем думать о вашей реализации проверки типов как о конкретной модели для рассматриваемой теории типов. Таким образом, вы хотите доказать это двустороннее соответствие между тем, что может сделать ваша реализация, и тем, что, согласно теории, вы должны делать. Преимуществом этой перспективы является то, что она действительно фокусируется на том, охватили ли вы все ключевые случаи, завершена ли ваша реализация в смысле того, чтобы не исключать какие-либо программы, которые она должна принимать как безопасные с точки зрения типов, и является ли ваша реализация надежной в смысл не пускать в какие-либо программы его следует отвергать как плохо напечатанные. Недостатком является то, что ваше доказательство соответствия, вероятно, будет достаточно отделено от самой реализации,

Рен Романо
источник
Я не уверен, что могу согласиться с «положительным аспектом этой перспективы является то, что она действительно фокусируется на том, покрыли ли вы все угловые случаи», особенно если модель является только надежной, но не законченной. Я бы предложил другую точку зрения: прохождение модели - это условный метод доказательства, который вы используете по разным причинам, например, потому что модель проще. Нет ничего философски более достойного в прохождении модели - в конечном итоге вы хотите знать о реальном исполняемом файле и его поведении.
Мартин Бергер
Я думал, что «модель» и «теория» подразумевались в широком смысле, и Рен просто подчеркивал важность попыток установить двустороннее соответствие с помощью «теоремы разумности + полноты». (Я также думаю, что это важно, и сделал комментарий к посту Андрея.) Это правда, что в некоторых ситуациях мы сможем доказать только теорему обоснованности (или теорему о полноте, в зависимости от вашей перспективы), но имея оба направления Имеется в виду полезное методологическое ограничение.
Ноам
1
@NoamZeilberger «Вопрос в том, - сказал Мартин, - можете ли вы сделать так, чтобы слова означали так много разных вещей».
Мартин Бергер
Когда я узнал о типизации систем и семантики языка программирования, я обнаружил, что модели - это всего лишь доказательство техники операционной семантики, а не самоцель, возвышенное освобождение.
Мартин Бергер
1
Отношение к различным моделям через разумность и полноту является важной научной методологией для передачи понимания.
Мартин Бергер