Теорія залежних типів і функції "довільного" типу
Моя перша відповідь на це запитання була високо понятною і мало детальною і відображена під питанням: "що відбувається?"; ця відповідь буде такою ж, але зосереджена на підзапиті, "чи можна отримати функції довільного типу?".
Одне розширення алгебраїчних операцій суми і твори є так звані «великі оператори», які представляють собою суму і твір послідовності (або в більш загальному плані , суми і добутку функції над областю) , як правило , написані Σ
і Π
відповідно. Див. Позначення Sigma .
Отже сума
a₀ + a₁X + a₂X² + ...
може бути написано
Σ[i ∈ ℕ]aᵢXⁱ
де a
є певна послідовність дійсних чисел, наприклад. Продукт буде представлений аналогічно Π
замість Σ
.
Якщо дивитися здалеку, такий вираз виглядає як «довільна» функція X
; ми, звичайно, обмежені виразними рядами та пов'язаними з ними аналітичними функціями. Це кандидат у представництво в теорії типів? Безумовно!
Клас теорій типів, що мають безпосереднє уявлення про ці вирази, - це клас теорій "залежних" типів: теорії із залежними типами. Природно, у нас є терміни, залежні від термінів, і в таких мовах, як Haskell, з функціями типу та кількісним визначенням типу, термінами та типами залежно від типів. У залежних умовах ми додатково маємо типи залежно від термінів. Haskell не є залежно типізованою мовою, хоча багато особливостей залежних типів можна імітувати , трохи тортуючи мову .
Каррі-Говард та залежні типи
«Ізоморфізм Крірі-Говарда» розпочав життя як спостереження про те, що терміни та правила судження про просто набране лямбда-числення точно відповідають природній дедукції (сформульованій Генцену), застосованій до інтуїтивної логіки пропозицій, причому типи займають місце пропозицій , а також терміни, що займають місце доказів, незважаючи на те, що два незалежно винайдені / виявлені З тих пір це величезне джерело натхнення для теоретиків типів. Однією з найбільш очевидних речей, на яку слід звернути увагу, є те, чи може, і як ця відповідність логіці пропозицій може бути розширена до логіки предикатів або вищого порядку Спочатку теорії залежних типів виникли з цього напряму розвідки.
Про вступ до ізоморфізму Крірі-Говарда для просто набраного лямбдального числення дивіться тут . Наприклад, якщо ми хочемо довести, A ∧ B
ми повинні довести A
і довести B
; комбінований доказ - це просто пара доказів: по одному для кожного сполучника.
При природній дедукції:
Γ ⊢ A Γ ⊢ B
Γ ⊢ A ∧ B
і в просто введеному лямбдальному обчисленні:
Γ ⊢ a : A Γ ⊢ b : B
Γ ⊢ (a, b) : A × B
Подібні відповідники існують для ∨
типів і сум, →
і типів функцій, і різних правил усунення.
Недоказуваному (інтуїціоністично помилковому) судження відповідає ненаселеному типу.
Маючи на увазі аналогію типів як логічних пропозицій, ми можемо почати розглядати, як моделювати предикати у типовому світі. Існує багато способів, як це було формалізовано (див. Це вступ до теорії інтуїціоністичного типу Мартіна-Лефа для широко використовуваного стандарту), але абстрактний підхід зазвичай зауважує, що предикат є як пропозиція із змінними вільних термінів, або, як альтернатива, функція, що приймає умови до пропозицій. Якщо ми дозволяємо виразам типів містити терміни, то лікування в стилі обчислення лямбда негайно представляє себе як можливість!
Вважаючи лише конструктивні докази, що є доказом ∀x ∈ X.P(x)
? Ми можемо вважати це функцією доказування, приймаючи умови ( x
) до доказів відповідних пропозицій ( P(x)
). Тому члени (докази) типу (пропозиція) ∀x : X.P(x)
є «залежні функції», які для кожного x
в X
дають термін типу P(x)
.
Про що ∃x ∈ X.P(x)
? Нам потрібен будь-який член X
, x
разом з доказом P(x)
. Таким чином , члени (докази) типу (пропозиція) ∃x : X.P(x)
є «залежні пари»: відзначений термін x
в X
, разом з терміном типу P(x)
.
Позначення: я буду використовувати
∀x ∈ X...
для фактичних тверджень про членів класу X
та
∀x : X...
для виразів типів, що відповідають універсальній кількісній оцінці щодо типу X
. Так само і для ∃
.
Комбінаторні міркування: продукти та суми
Як і відповідність типів Крірі-Говарда з пропозиціями, ми маємо комбінаторну відповідність алгебраїчних типів з числами та функціями, що є основним моментом цього питання. На щастя, це можна поширити на залежні типи, описані вище!
Я буду використовувати позначення модуля
|A|
представляти "розмір" типу A
, чітко визначати відповідність, викладену у запитанні, між типами та номерами. Зауважте, що це поняття поза теорією; Я не стверджую, що потрібен будь-який такий оператор у межах мови.
Порахуймо можливих (повністю скорочених, канонічних) членів типу
∀x : X.P(x)
що є типом залежних функцій, що приймають терміни x
типу X
до термінів типу P(x)
. Кожна така функція повинна мати вихід на кожен термін X
, і цей вихід повинен мати певний тип. Тоді для кожного x
з них X
це дає |P(x)|
"вибір" виходу.
Пунктин є
|∀x : X.P(x)| = Π[x : X]|P(x)|
що, звичайно, не має великого сенсу, якщо X
є IO ()
, але застосовно до алгебраїчних типів.
Аналогічно термін типу
∃x : X.P(x)
- це тип пар (x, p)
з p : P(x)
, тому, даючи будь-який x
в, X
ми можемо побудувати відповідну пару з будь-яким членом P(x)
, даючи |P(x)|
"вибір".
Отже,
|∃x : X.P(x)| = Σ[x : X]|P(x)|
з тими ж застереженнями.
Це виправдовує загальне позначення залежних типів у теоріях із використанням символів, Π
і Σ
, дійсно, багато теорій розмивають відмінність "для всіх" і "продукт", а також "існує" і "сума" через вищезазначені відповідники.
Ми наближаємось!
Вектори: представлення залежних кортежів
Чи можемо ми тепер кодувати числові вирази, як
Σ[n ∈ ℕ]Xⁿ
як вирази типів?
Не зовсім. Хоча ми можемо неофіційно розглянути значення виразів, як Xⁿ
у Haskell, де X
це тип і n
натуральне число, це зловживання позначенням; це вираз типу, що містить число: явно не є дійсним виразом.
З іншого боку, із залежними типами на малюнку типи, що містять числа, є саме точкою; насправді залежні кортежі або "вектори" є дуже поширеним прикладом того, як залежні типи можуть забезпечити прагматичну безпеку на рівні типу для таких операцій, як доступ до списку . Вектор - це лише список, а також інформація про рівень типу щодо його довжини: саме те, про що ми хочемо, для виразів типу Xⁿ
.
На час цієї відповіді нехай
Vec X n
- тип n
векторів X
довжини значень -типу.
Технічно n
тут є, а не фактичне натуральне число, представленням у системі натурального числа. Ми можемо представити натуральні числа ( Nat
) у стилі Пеано як нуль ( 0
) або наступник ( S
) іншого природного числа, і n ∈ ℕ
я пишу, ˻n˼
щоб означати термін, у Nat
якому зображено n
. Наприклад, ˻3˼
є S (S (S 0))
.
Тоді маємо
|Vec X ˻n˼| = |X|ⁿ
для будь-якого n ∈ ℕ
.
Nat типи: просування ℕ термінів до типів
Тепер ми можемо кодувати вирази типу
Σ[n ∈ ℕ]Xⁿ
як види. Цей конкретний вираз породжує тип, який, звичайно, ізоморфний типу списків X
, визначених у питанні. (Мало того, але з теоретично-теоретичної точки зору функція типу - яка є функтором - перенесення X
до вищевказаного типу, природно є ізоморфною для функтора списку.)
Один заключний фрагмент головоломки для "довільних" функцій - це кодування, для
f : ℕ → ℕ
вирази, як
Σ[n ∈ ℕ]f(n)Xⁿ
щоб ми могли застосувати довільні коефіцієнти до ряду потужностей.
Ми вже розуміємо відповідність алгебраїчних типів цифрам, що дозволяє нам зіставляти від типів до чисел, а функції типу - до числових функцій. Ми також можемо піти іншим шляхом! - Беручи натуральне число, очевидно, що можна визначити алгебраїчний тип з такою кількістю членів терміна, незалежно від того, чи є у нас залежні типи. Ми можемо легко довести це поза теорією типу індукцією. Нам потрібен спосіб відображення натуральних чисел на типи всередині системи.
Приємно зрозуміти, що коли ми маємо залежні типи, доказ за допомогою індукції та побудови за допомогою рекурсії стає дуже близьким - насправді вони є тим самим ділом у багатьох теоріях. Оскільки ми можемо за допомогою індукції довести, що існують типи, які задовольняють наші потреби, чи не можемо ми їх побудувати?
Існує кілька способів представлення типів на рівні терміна. Я буду використовувати тут уявну хаскельську позначення з *
для Всесвіту типів, що зазвичай вважається типом у залежній обстановці. 1
Аналогічно, існує також щонайменше стільки ж способів позначити " ℕ
-значення", скільки існує теорій залежного типу. Я буду використовувати позначення відповідності шаблону Haskellish.
Нам необхідно відображення, α
від Nat
до *
, з властивістю
∀n ∈ ℕ.|α ˻n˼| = n.
Наступного псевдоопределення достатньо.
data Zero -- empty type
data Successor a = Z | Suc a -- Successor ≅ Maybe
α : Nat -> *
α 0 = Zero
α (S n) = Successor (α n)
Отже ми бачимо, що дія α
дзеркально відображає поведінку наступника S
, роблячи це свого роду гомоморфізмом. Successor
- це функція типу, яка "додає один" до числа членів типу; тобто |Successor a| = 1 + |a|
для будь-якого a
із визначеним розміром.
Наприклад α ˻4˼
(що є α (S (S (S (S 0))))
), є
Successor (Successor (Successor (Successor Zero)))
і терміни цього типу є
Z
Suc Z
Suc (Suc Z)
Suc (Suc (Suc Z))
даючи нам точно чотири елементи: |α ˻4˼| = 4
.
Крім того, для будь-якого n ∈ ℕ
, у нас є
|α ˻n˼| = n
по мірі необхідності.
- Багато теорій вимагають, щоб члени
*
були просто представниками типів, і операція забезпечується як явне відображення від термінів типу *
до їх асоційованих типів. Інші теорії дозволяють самим буквальним типам бути суб'єктами термінового рівня.
'Довільні' функції?
Тепер у нас є апарат для вираження цілком загального ряду потужностей як типу!
Серія
Σ[n ∈ ℕ]f(n)Xⁿ
стає типом
∃n : Nat.α (˻f˼ n) × (Vec X n)
де ˻f˼ : Nat → Nat
є якесь відповідне представлення в мові функції f
. Ми можемо побачити це так.
|∃n : Nat.α (˻f˼ n) × (Vec X n)|
= Σ[n : Nat]|α (˻f˼ n) × (Vec X n)| (property of ∃ types)
= Σ[n ∈ ℕ]|α (˻f˼ ˻n˼) × (Vec X ˻n˼)| (switching Nat for ℕ)
= Σ[n ∈ ℕ]|α ˻f(n)˼ × (Vec X ˻n˼)| (applying ˻f˼ to ˻n˼)
= Σ[n ∈ ℕ]|α ˻f(n)˼||Vec X ˻n˼| (splitting product)
= Σ[n ∈ ℕ]f(n)|X|ⁿ (properties of α and Vec)
Наскільки це "довільно"? Цим методом ми обмежені не лише цілими коефіцієнтами, а й натуральними числами. Крім того, що f
може бути будь-що взагалі, з огляду на мову Тюрінга Повної із залежними типами, ми можемо представляти будь-яку аналітичну функцію з натуральними коефіцієнтами чисел.
Я не досліджував взаємодію цього питання, наприклад, із випадком, передбаченим у запитанні, List X ≅ 1/(1 - X)
або який можливий сенс можуть мати такі негативні та не цілі "типи" в цьому контексті.
Сподіваємось, ця відповідь певним чином вивчає, наскільки далеко ми можемо пройти функції довільного типу.