Этот синтаксис, хотя и может показаться сложным, на самом деле довольно прост. Основная идея исходит из формальной логики: все выражение является следствием, причем верхняя половина - это предположения, а нижняя - результат. То есть, если вы знаете, что верхние выражения верны, вы можете сделать вывод, что нижние выражения также верны.
Символы
Следует также помнить, что некоторые буквы имеют традиционное значение; в частности, Γ представляет «контекст», в котором вы находитесь, то есть типы других вещей, которые вы видели. Итак, что-то вроде Γ ⊢ ...означает «выражение, ...когда вы знаете типы каждого выражения в Γ.
⊢Символ по существу означает , что вы можете что - то доказать. Так Γ ⊢ ...же как и утверждение «Я могу доказать ...в контексте Γ. Эти утверждения также называются суждениями типа».
Следует иметь в виду еще одну вещь: в математике, как и в ML и Scala, x : σподразумевается, что у xнее есть тип σ. Вы можете прочитать это так же, как у Хаскелла x :: σ.
Что означает каждое правило
Итак, зная это, первое выражение становится легко понять: если мы знаем, что x : σ ∈ Γ(то есть, xимеет некоторый тип σв некотором контексте Γ), то мы знаем, что Γ ⊢ x : σ(то есть Γ, xимеет тип σ). Так что на самом деле, это не говорит вам ничего супер-интересного; это просто говорит вам, как использовать ваш контекст.
Другие правила также просты. Например, взять [App]. Это правило имеет два условия: e₀это функция от некоторого типа τк некоторому типу τ'и e₁значение типа τ. Теперь вы знаете, какой тип вы получите, обратившись e₀к e₁! Надеюсь, это не удивительно :).
Следующее правило имеет еще один новый синтаксис. В частности, Γ, x : τпросто означает контекст Γи суждение x : τ. Итак, если мы знаем, что переменная xимеет тип, τа выражение eимеет тип τ', мы также знаем тип функции, которая принимает xи возвращает e. Это просто говорит нам, что делать, если мы выяснили, какой тип принимает функция и какой тип она возвращает, поэтому это тоже не должно удивлять.
Следующий просто говорит вам, как обрабатывать letзаявления. Если вы знаете, что какое-то выражение e₁имеет тип τдо тех пор, пока оно xимеет тип σ, то letвыражение, которое локально связывается xсо значением типа, σбудет e₁иметь тип τ. На самом деле, это просто говорит вам, что оператор let по сути позволяет вам расширять контекст с помощью новой привязки, что и letделает!
[Inst]Правило касается суб-печати. Это говорит о том, что если у вас есть значение типа σ'и оно является подтипом σ( ⊑представляет отношение частичного упорядочения), то это выражение также имеет тип σ.
Последнее правило касается обобщающих типов. Небольшое отступление: свободная переменная - это переменная, которая не вводится оператором let или лямбда-выражением внутри некоторого выражения; это выражение теперь зависит от значения свободной переменной из ее контекста. Правило гласит, что если есть некоторая переменная, αкоторая не является «свободной» ни в чем в вашем контексте, то можно с уверенностью сказать, что любое выражение, тип которого вы знаете, e : σбудет иметь этот тип для любого значения α.
Как пользоваться правилами
Итак, теперь, когда вы понимаете символы, что вы делаете с этими правилами? Ну, вы можете использовать эти правила, чтобы выяснить тип различных значений. Чтобы сделать это, посмотрите на свое выражение (скажем f x y) и найдите правило, в котором есть заключение (нижняя часть), соответствующее вашему утверждению. Давайте назовем то, что вы пытаетесь найти своей «целью». В этом случае вы бы посмотрели на правило, которое заканчивается e₀ e₁. Когда вы нашли это, теперь вы должны найти правила, доказывающие все, что находится выше линии этого правила. Эти вещи, как правило, соответствуют типам подвыражений, так что вы по существу повторяете части выражения. Вы просто делаете это, пока не закончите свое дерево доказательств, которое дает вам подтверждение типа вашего выражения.
Таким образом, все эти правила указывают точно - и в обычной математически педантичной детали: P - как выяснить типы выражений.
Теперь, это должно звучать знакомо, если вы когда-либо использовали Пролог - вы по сути вычисляете дерево доказательств, как человеческий интерпретатор Пролога. Есть причина, по которой Пролог называют «логическим программированием»! Это также важно, так как я впервые познакомился с алгоритмом вывода HM, реализовав его в Прологе. Это на самом деле удивительно просто и проясняет то, что происходит. Вы должны обязательно попробовать это.
Примечание: я, вероятно, допустил некоторые ошибки в этом объяснении и был бы рад, если бы кто-то на них указал. На самом деле я расскажу об этом в классе через пару недель, поэтому я буду более уверенным в этом: P.