Изоморфизм Карри-Говарда
Я искал в интернете, и я не могу найти никаких объяснений Ци, которые не быстро вырождаются в лекцию по теории логики, которая резко над моей головой. (Эти люди говорят, что "интуитивистское исчисление пропозиций" - это фраза, которая на самом деле значит что-то для нормальных людей!)
грубо говоря, Ци говорит, что типы являются теоремами, а программы-доказательствами этих теорем. Но какого черта это вообще mean??
до сих пор я понял это:
считают
id :: x -> x
. Его тип говорит: "учитывая, что X истинно, мы можем заключить, что X истинно". Мне кажется, это разумная теорема.Теперь рассмотрим
foo :: x -> y
. Как скажет вам любой программист Haskell, это невозможно. Вы не можете написать эту функцию. (Ну, во всяком случае без обмана.) Прочитайте как теорему, она говорит: "учитывая, что любой X истинен, мы можем заключить, что любой Y правдивый." Это, очевидно, бред. И, конечно же, вы не можете написать эту функцию.в более общем плане аргументы функции можно рассматривать как "это, которое предполагается истинным", а тип результата можно рассматривать как"вещь, которая истинна, если все остальные вещи". Если есть аргумент функции, скажите
x -> y
, мы можем принять это как предположение, что X истинно означает, что Y должно быть истинным.например,
(.) :: (y -> z) -> (x -> y) -> x -> z
can "если предположить, что Y подразумевает Z, что X подразумевает Y и что X истинно, мы можем заключить, что Z истинно". Что кажется мне логически разумным.
теперь, что, черт возьми Int -> Int
в смысле?? О_о
единственный разумный ответ, который я могу придумать, это: если у вас есть функция X - > Y - > Z, то подпись типа говорит: "предполагая, что можно построить значение типа X, а другое типа Y, то можно построить значение типа Зет." И тело функции точно описывает, как вы это сделаете.
это, кажется, имеет смысл, но это не очень интересные. Ясно, что за этим кроется нечто большее...
3 ответов
изоморфизм Карри-Говарда просто утверждает, что типы соответствуют пропозициям, а значения соответствуют доказательствам.
Int -> Int
на самом деле не означает много интересного как логическое предложение. При интерпретации чего-либо как логического предложения вас интересует только то, является ли тип Обитаемый (имеет никакого значения) или нет. Итак,Int -> Int
значит "дали Int
, Я могу дать вам - это просто определенный вид логики, которому соответствуют общие функциональные языки. Важно отметить, что это конструктивное: в принципе, доказательство a -> b
дает алгоритм вычислить b
С a
, что неверно в обычной классической логике (из-за закон исключенного третьего, который скажет вам, что что-то либо истинно, либо ложно, но не почему).
даже если функции как Int -> Int
не много значит как предложения, мы можем делать утверждения о них с другими предложениями. Например, мы можем объявить тип равенства двух типов (используя GADT):
data Equal a b where
Refl :: Equal a a
если у нас есть значение типа Equal a b
, потом a
тот же тип b
: Equal a b
соответствующее предложение a = b. Проблема в том, что мы можем говорить только о равенстве типы этот путь. Но если бы мы ... зависимые типы, мы могли бы легко обобщить это определение для работы с любой значением, и так Equal a b
соответствовало бы предположению, что значения a и b идентичны. Так, например, мы могли бы написать:--25-->
type IsBijection (f :: a -> b) (g :: b -> a) =
forall x. Equal (f (g x)) (g (f x))
здесь f и g обычные функции, так f может легко иметь тип Int -> Int
. Опять же, Хаскелл не может этого сделать; вам нужно зависимые типы делают такие вещи.
типичные функциональные языки не очень хорошо подходят для написания доказательств не только потому, что им не хватает зависимых типов, но и из-за⊥, который, имея тип a
для всех a
, действует как доказательство любого предложения. Но!--83-->в общей сумме языки, как Coq и Agda использовать переписку в качестве системы доказательств, а также зависимо-типизированный программирования языки.
возможно, лучший способ понять, что это означает начать (или попробовать) используя типы как предложения и программы в качестве доказательств. Лучше изучать язык с зависимыми типами, такими как Agda (это написано в Haskell и похоже на Haskell). Существуют различные статьи и курсы на этом языке. узнать вас Agda является неполным, но стараюсь все упрощать, как LYAHFGG книга.
вот пример простого доказательства:
{-# OPTIONS --without-K #-} -- we are consistent
module Equality where
-- Peano arithmetic.
--
-- ℕ-formation: ℕ is set.
--
-- ℕ-introduction: o ∈ ℕ,
-- a ∈ ℕ | (1 + a) ∈ ℕ.
--
data ℕ : Set where
o : ℕ
1+ : ℕ → ℕ
-- Axiom for _+_.
--
-- Form of ℕ-elimination.
--
infixl 6 _+_
_+_ : ℕ → ℕ → ℕ
o + m = m
1+ n + m = 1+ (n + m)
-- The identity type for ℕ.
--
infix 4 _≡_
data _≡_ (m : ℕ) : ℕ → Set where
refl : m ≡ m
-- Usefull property.
--
cong : {m n : ℕ} → m ≡ n → 1+ m ≡ 1+ n
cong refl = refl
-- Proof _of_ mathematical induction:
--
-- P 0, ∀ x. P x → P (1 + x) | ∀ x. P x.
--
ind : (P : ℕ → Set) → P o → (∀ n → P n → P (1+ n)) → ∀ n → P n
ind P P₀ _ o = P₀
ind P P₀ next (1+ n) = next n (ind P P₀ next n)
-- Associativity of addition using mathematical induction.
--
+-associative : (m n p : ℕ) → (m + n) + p ≡ m + (n + p)
+-associative m n p = ind P P₀ is m
where
P : ℕ → Set
P i = (i + n) + p ≡ i + (n + p)
P₀ : P o
P₀ = refl
is : ∀ i → P i → P (1+ i)
is i Pi = cong Pi
-- Associativity of addition using (dependent) pattern matching.
--
+-associative′ : (m n p : ℕ) → (m + n) + p ≡ m + (n + p)
+-associative′ o _ _ = refl
+-associative′ (1+ m) n p = cong (+-associative′ m n p)
там вы можете увидеть (m + n) + p ≡ m + (n + p)
предложение как тип и его доказательство как функция. Существуют более продвинутые методы для таких доказательств (например, предзаказ рассуждения, комбинаторы в Agda похожи на тактику в Coq).
что еще можно доказать:
head ∘ init ≡ head
для векторов, здесь.ваш компилятор создает программу какое выполнение дает то же значение, что и значение, полученное в интерпретации той же (хост -) программы, здесь, для Coq. книги также является хорошим чтением по теме моделирования языка и проверки программ.
все остальное, что может быть доказано в конструктивной математике, так как теория типов Мартина-Лефа в своей выразительной силе эквивалентна ZFC. Фактически, изоморфизм Карри-Говарда может быть расширен до физика и топология и алгебраической топологии.
единственный разумный ответ, который я могу придумать, таков: Если у вас есть функция X -> Y -> Z, то подпись типа говорит: "предполагая, что можно построить значение типа X, а другое типа Y, то можно построить значение типа Z". И тело функции точно описывает, как вы это сделаете. В этом есть смысл, но это не очень интересно. Ясно, что за этим кроется нечто большее...
Ну, да, есть гораздо больше, потому что это имеет много последствий и открывает много вопросов.
прежде всего, ваше обсуждение Ци оформлено исключительно в терминах типов импликации / функции (->
). Вы не говорите об этом, но вы, вероятно, видели, как конъюнкция и дизъюнкция соответствуют типам продукта и суммы соответственно. Но как насчет других логических операторов, таких как отрицание, универсальная квантификация и экзистенциальная квантификация? Как мы перевести логические доказательства, связанные с ними, в программы? Получается, что примерно так:
- отрицание соответствует первоклассные продолжения. Не проси меня объяснить это.
- универсальная квантификация над пропозициональными (не индивидуальными) переменными соответствует параметрический полиморфизм. Так, например, полиморфная функция
id
действительно имеет типforall a. a -> a
- экзистенциальное квантификация над пропозициональными переменными соответствует нескольким вещам, которые имеют отношение к скрытию данных или реализации:абстрактные типы данных, системы и динамическая диспетчеризация. Экзистенциальные типы GHC связаны с этим.
- универсальная и экзистенциальная квантификация по отдельным переменным приводит к зависимые системы типов.
кроме этого, это также означает, что все виды доказательств о логике мгновенно переводятся в доказательства о языках программирования. Например, разрешимость интуитивистской пропозициональной логики подразумевает прекращение всех программ в простом типизированном лямбда-исчислении.
теперь, что, черт возьми, означает Int - > Int?? О_о
это тип, или же предложение. В f :: Int -> Int
, (+1)
называет " программу "(в определенном смысле, который допускает как функции, так и константы как "программы", или альтернативно доказательство. Семантика языка должна либо обеспечивать f
как примитивное правило вывода, или продемонстрировать, как f
является доказательством, которое может быть построено из таких правил и предпосылок.
эти правила часто указываются с точки зрения эквациональной аксиом, которые определяют члены базового типа и правила, которые позволяют доказать, что других программ населяют этот тип. Например, переключение с Int
to Nat
(натуральные числа от 0 forward), мы могли бы иметь следующие правила:
- аксиомы:
0 :: Nat
(0
примитивное доказательствоNat
) - правила:
x :: Nat ==> Succ x :: Nat
- правила:
x :: Nat, y :: Nat ==> x + y :: Nat
- правила:
x + Zero :: Nat ==> x :: Nat
- правила:
Succ x + y ==> Succ (x + y)
эти правила достаточно, чтобы доказать многие теоремы о сложении натуральных чисел. Эти доказательства также будут программами.