Я клянусь , там раньше была футболкой для продажи с участием бессмертных слов:
Какая часть
ты не понимаешь?
В моем случае ответ будет ... все это!
В частности, я часто вижу подобные обозначения в документах на Haskell, но я понятия не имею, что это означает. Я понятия не имею, какой отраслью математики она должна быть.
Я, конечно, узнаю буквы греческого алфавита и такие символы, как «∉» (что обычно означает, что что-то не является элементом набора).
С другой стороны, я никогда раньше не видел «⊢» ( Википедия утверждает, что это может означать «раздел» ). Я также незнаком с использованием винкулума здесь. ( Как правило, это означает фракцию, но не появляется , чтобы быть в этом случае.)
Если бы кто-нибудь мог хотя бы сказать мне, с чего начать поиск, чтобы понять, что означает это море символов, это было бы полезно.
источник
Ответы:
:
значит имеет тип∈
значит в . (Точно так же∉
означает «не в».)Γ
обычно используется для обозначения среды или контекста; в этом случае его можно рассматривать как набор аннотаций типов, связывающих идентификатор с его типом. Следовательно,x : σ ∈ Γ
означает, что средаΓ
включает в себя тот факт, чтоx
имеет типσ
.⊢
может быть прочитано как доказывает или определяет.Γ ⊢ x : σ
означает, что средаΓ
определяет, чтоx
имеет типσ
.,
это способ включения конкретных дополнительных допущений в окружающую средуΓ
.Таким образом,
Γ, x : τ ⊢ e : τ'
означает , что окружающая средаΓ
, с дополнительным, отвергая предположение , чтоx
имеет типτ
, доказывает , чтоe
имеет типτ'
.По запросу: приоритет оператора, от наивысшего к низшему:
λ x . e
,∀ α . σ
, иτ → τ'
,let x = e0 in e1
и пробельная для применения функции.:
∈
а также∉
,
(Левоассоциативные)⊢
источник
:
и∈
очень похожи в том смысле, что они означают, что одна вещь содержится в другой вещи: набор содержит элементы, а тип в некотором смысле содержит значения. Принципиальное отличие состоит в том,x ∈ S
что это означает, что наборS
буквально содержит элементx
, тогда какΓ ⊢ x : T
означает, что онx
может быть выведен для обитания типаT
в контекстеΓ
. Учитывая это, правило Var гласит: «Если x буквально содержится в контексте, из него можно (тривиально) вывести«.(Γ,(x:τ))⊢(x:σ)
, см overleaf.com/read/ddmnkzjtnqbd#/61990222Этот синтаксис, хотя и может показаться сложным, на самом деле довольно прост. Основная идея исходит из формальной логики: все выражение является следствием, причем верхняя половина - это предположения, а нижняя - результат. То есть, если вы знаете, что верхние выражения верны, вы можете сделать вывод, что нижние выражения также верны.
Символы
Следует также помнить, что некоторые буквы имеют традиционное значение; в частности, Γ представляет «контекст», в котором вы находитесь, то есть типы других вещей, которые вы видели. Итак, что-то вроде
Γ ⊢ ...
означает «выражение,...
когда вы знаете типы каждого выражения вΓ
.⊢
Символ по существу означает , что вы можете что - то доказать. ТакΓ ⊢ ...
же как и утверждение «Я могу доказать...
в контекстеΓ
. Эти утверждения также называются суждениями типа».Следует иметь в виду еще одну вещь: в математике, как и в 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.
источник
Γ = {x : τ}
)λy.x : σ → τ
до∀ σ. σ → τ
, но не∀ τ. σ → τ
, потому чтоτ
это свободная переменнаяΓ
. Статья в Википедии об HM объясняет это довольно хорошо.[Inst]
немного неточна. Это только мое понимание до сих пор, но сигмы в[Inst]
и[Gen]
правила не относятся к типам, а тип-схемы . Таким образом,⊑
оператор является частичным порядком, не связанным с подтипом, как мы его знаем из ОО-языков. Это связано с полиморфными значениями, такими какid = λx. x
. Полный синтаксис для такой функции был быid = ∀x. λx. x
. Теперь мы можем, очевидно, иметьid2 = ∀xy. λx. x
, гдеy
не используется. Тогдаid2 ⊑ id
это то, что[Inst]
говорит правило.См. « Практические основы языков программирования », главы 2 и 3, о стиле логики через суждения и выводы. Вся книга теперь доступна на Amazon.
Глава 2
Индуктивные определения
Индуктивные определения являются незаменимым инструментом в изучении языков программирования. В этой главе мы разработаем основные рамки индуктивных определений и приведем несколько примеров их использования. Индуктивное определение состоит из набора правил для выведения суждений или утверждений различных форм. Суждения - это утверждения об одном или нескольких синтаксических объектах указанного вида. Правила определяют необходимые и достаточные условия для действительности решения и, следовательно, полностью определяют его значение.
2.1 Суждения
Мы начнем с понятия суждения или утверждения о синтаксическом объекте. Мы будем использовать многие формы суждения, включая такие примеры:
Суждение гласит, что один или несколько синтаксических объектов имеют свойство или стоят в некотором отношении друг к другу. Само свойство или отношение называется формой суждения , а суждение о том, что объект или объекты обладают этим свойством или позицией в этом отношении, называется экземпляром этой формы суждения. Форма суждения также называется предикатом , а объекты, составляющие экземпляр, являются его субъектами . Запишем в J для решения утверждающего , что J трюмах . Когда не важно подчеркнуть предмет суждения (текст обрывается здесь)
источник
Как я понимаю правила Хиндли-Милнера?
Хиндли-Милнер - это набор правил в форме последовательного исчисления (не естественного вывода), который демонстрирует, что мы можем вывести (наиболее общий) тип программы из конструкции программы без явных объявлений типов.
Символы и обозначения
Сначала объясним символы и обсудим приоритет операторов
𝜆𝑥.𝑒 означает, что 𝜆 (лямбда) является анонимной функцией, которая принимает аргумент 𝑥 и возвращает выражение 𝑒 .
пусть 𝑥 = 𝑒₀ в 𝑒₁ означает в выражении 𝑒₁ , замените 𝑒₀ везде, где 𝑥 появляется.
⊑ означает, что предыдущий элемент является подтипом (неофициально - подкласс) последнего элемента.
Все выше линии - предпосылка, все ниже - заключение ( Пер Мартин-Лёф )
Приоритет, на примере
Я взял некоторые из более сложных примеров из правил и вставил лишние скобки, которые показывают приоритет:
𝚪 ⊦ 𝑥 : 𝜎 можно написать 𝚪 ⊦ ( 𝑥 : 𝜎 )
Г ⊦ пусть 𝑥 = 𝑒₀ в 𝑒₁ : τ это равносильно Γ ⊦ (( пусть ( 𝑥 = 𝑒₀ ) в 𝑒₁ ): τ )
𝚪 ⊦ 𝜆𝑥.𝑒 : 𝜏 → 𝜏 ' эквивалентно 𝚪 ⊦ (( 𝜆𝑥.𝑒 ): ( 𝜏 → 𝜏' ))
Затем большие пробелы, отделяющие утверждения-утверждения и другие предварительные условия, указывают на набор таких предварительных условий, и, наконец, горизонтальная линия, отделяющая предпосылку от заключения, приводит к концу порядка предшествования.
Правила
Ниже следует толкование правил на английском языке, каждое из которых сопровождается свободной переформулировкой и пояснением.
переменная
Другими словами, в 𝚪 мы знаем, что 𝑥 имеет тип 𝜎, потому что 𝑥 имеет тип 𝜎 в 𝚪.
Это в основном тавтология. Имя идентификатора - это переменная или функция.
Применение функции
Чтобы переформулировать правило, мы знаем, что приложение функции возвращает тип 𝜏 ', потому что функция имеет тип 𝜏 → 𝜏' и получает аргумент типа 𝜏.
Это означает, что если мы знаем, что функция возвращает тип, и мы применяем его к аргументу, результатом будет экземпляр возвращаемого нами типа.
Функция Абстракция
Опять же, когда мы видим функцию, которая принимает 𝑥 и возвращает выражение 𝑒, мы знаем, что она имеет тип 𝜏 → 𝜏 ', потому что 𝑥 (a 𝜏) утверждает, что 𝑒 является 𝜏'.
Если мы знаем, что 𝑥 имеет тип 𝜏 и, следовательно, выражение 𝑒 имеет тип 𝜏 ', то функция of, возвращающая выражение 𝑒, имеет тип 𝜏 → 𝜏'.
Пусть объявление переменной
Слабо, 𝑥 связан с 𝑒₀ в 𝑒₁ (a 𝜏), потому что 𝑒₀ является 𝜎, а 𝑥 является 𝜎, который утверждает, что 𝑒₁ является 𝜏.
Это означает, что если у нас есть выражение 𝑒₀, представляющее собой 𝜎 (являющееся переменной или функцией), и некоторое имя 𝑥, также a a, и выражение 𝑒₁ типа 𝜏, то мы можем заменить 𝑒₀ на 𝑒₀, где бы оно ни находилось внутри 𝑒₁.
Конкретизация
Выражение 𝑒 имеет родительский тип 𝜎, поскольку выражение 𝑒 является подтипом 𝜎 ', а 𝜎 является родительским типом 𝜎'.
Если экземпляр имеет тип, который является подтипом другого типа, то он также является экземпляром этого супертипа - более общего типа.
Обобщение
Таким образом, в общем случае, 𝑒 типизирован 𝜎 для всех переменных аргумента (𝛼), возвращающих 𝜎, потому что мы знаем, что 𝑒 является 𝜎, а 𝛼 не является свободной переменной.
Это означает, что мы можем обобщить программу для принятия всех типов для аргументов, которые еще не связаны в содержащей области (переменные, которые не являются нелокальными). Эти связанные переменные являются заменяемыми.
Собираем все вместе
Учитывая определенные предположения (такие как отсутствие свободных / неопределенных переменных, известная среда), мы знаем типы:
Вывод
В совокупности эти правила позволяют нам доказать наиболее общий тип утвержденной программы, не требуя аннотаций типов.
источник
Обозначение происходит от естественного вывода .
⊢ символ называется турникет .
6 правил очень просты.
Var
Правило является довольно тривиальным правилом - оно говорит, что если тип для идентификатора уже присутствует в вашей среде типов, то для вывода типа вы просто берете его из среды как есть.App
Правило говорит, что если у вас есть два идентификатораe0
и выe1
можете определить их типы, вы можете определить тип приложенияe0 e1
. Правило читается так, если вы знаете этоe0 :: t0 -> t1
иe1 :: t0
(то же самое t0!), Тогда приложение хорошо напечатано, а тип -t1
.Abs
иLet
являются правилами для вывода типов для лямбда-абстракции и ввода.Inst
Правило говорит, что вы можете заменить тип менее общим.источник
Есть два способа думать о е: σ. Одним из них является «выражение e имеет тип σ», другим является «упорядоченная пара выражения e и тип σ».
Рассматривайте Γ как знания о типах выражений, реализованные как набор пар выражений и типов, e: σ.
Турникет ⊢ означает, что из знания слева мы можем сделать вывод, что справа.
Таким образом, первое правило [Var] можно прочитать:
если наше знание Γ содержит пару e: σ, то мы можем вывести из Γ, что e имеет тип σ.
Второе правило [App] можно прочитать:
если мы из Γ можем вывести, что e_0 имеет тип τ → τ ', и мы из Γ можем вывести, что e_1 имеет тип τ, то мы из Γ можем вывести, что e_0 e_1 имеет Тип τ '.
Обычно пишут Γ, e: σ вместо Γ ∪ {e: σ}.
Таким образом, можно прочитать третье правило [Abs]:
если мы из Γ, расширенного с помощью x: τ, можем сделать вывод, что e имеет тип τ ', то мы из Γ можем сделать вывод, что λx.e имеет тип τ → τ'.
Четвертое правило [Позвольте] оставлено в качестве упражнения. :-)
Пятое правило [Inst] можно прочитать:
если мы из Γ можем вывести, что e имеет тип σ ', а σ' является подтипом σ, то мы из Γ можем вывести, что e имеет тип σ.
Шестое и последнее правило [Gen] можно прочитать:
если мы из Γ можем вывести, что e имеет тип σ, и α не является переменной свободного типа ни в одном из типов в Γ, то мы из Γ можем вывести, что e имеет тип ∀α σ.
источник