«Алгебраическое» выражение для алгебраических типов данных выглядит очень наводящим на размышления тому, кто имеет опыт работы в математике. Позвольте мне попытаться объяснить, что я имею в виду.
Определив основные типы
- Товар
•
- союз
+
- одиночка
X
- Ед. изм
1
и используя сокращение X²
для X•X
и 2X
для X+X
и так далее, мы можем затем определить алгебраические выражения, например, для связанных списков
data List a = Nil | Cons a (List a)
↔ L = 1 + X • L
и бинарные деревья:
data Tree a = Nil | Branch a (Tree a) (Tree a)
↔ T = 1 + X • T²
Теперь мой первый инстинкт как математика - сходить с ума с этими выражениями и попытаться решить для L
и T
. Я мог бы сделать это путем повторной замены, но, кажется, намного проще ужасно злоупотреблять обозначениями и притворяться, что я могу изменить их по своему желанию. Например, для связанного списка:
L = 1 + X • L
(1 - X) • L = 1
L = 1 / (1 - X) = 1 + X + X² + X³ + ...
где я использовал разложение степенных рядов 1 / (1 - X)
совершенно неоправданным способом, чтобы получить интересный результат, а именно, что L
тип является или Nil
, или он содержит 1 элемент, или он содержит 2 элемента, или 3, и т. д.
Будет интереснее, если мы сделаем это для бинарных деревьев:
T = 1 + X • T²
X • T² - T + 1 = 0
T = (1 - √(1 - 4 • X)) / (2 • X)
T = 1 + X + 2 • X² + 5 • X³ + 14 • X⁴ + ...
снова, используя расширение серии Power (сделано с Wolfram Alpha ). Это выражает неочевидный (для меня) факт, что существует только одно двоичное дерево с 1 элементом, 2 двоичных дерева с двумя элементами (второй элемент может находиться слева или справа), 5 двоичных деревьев с тремя элементами и т. Д. ,
Итак, мой вопрос - что я здесь делаю? Эти операции кажутся неоправданными (что такое квадратный корень алгебраического типа данных в любом случае?), Но они приводят к ощутимым результатам. имеет ли отношение два алгебраических типа данных какое-либо значение в информатике, или это просто нотационная хитрость?
И, возможно, более интересно, возможно ли расширить эти идеи? Существует ли теория алгебры типов, которая допускает, например, произвольные функции типов, или для типов требуется представление степенного ряда? Если вы можете определить класс функций, то имеет ли какое-либо значение композиция функций?
источник
Branch x (Branch y Nil Nil) Nil
или похожеBranch x Nil (Branch y Nil Nil)
.undefined
,throw
и т.д. Мы должны использовать его.Ответы:
Отказ от ответственности: многое из этого на самом деле не работает правильно, если учесть ⊥, поэтому я буду просто игнорировать это ради простоты.
Несколько начальных точек:
Обратите внимание , что «объединение», вероятно , не лучший термин для A + B здесь - вот конкретно непересекающихся объединение двух типов, так как обе стороны отличаются , даже если их типы совпадают. Для чего это стоит, более распространенный термин просто «тип суммы».
Синглтон-типы - это, по сути, все типы юнитов. Они ведут себя одинаково при алгебраических манипуляциях, и, что более важно, объем информации сохраняется до сих пор.
Вы, вероятно, хотите нулевой тип, а также. Haskell предоставляет это как
Void
. Нет значений, тип которых равен нулю, так же как есть одно значение, тип которого равен единице.Здесь все еще не хватает одной важной операции, но я вернусь к этому через минуту.
Как вы, наверное, заметили, Haskell имеет тенденцию заимствовать понятия из теории категорий, и все вышеперечисленное имеет очень простую интерпретацию как таковую:
Для объектов A и B в Hask их произведение A × B является уникальным (с точностью до изоморфизма) типом, который допускает две проекции fst : A × B → A и snd : A × B → B, где заданы любой тип C и функции f. : C → A, g : C → B вы можете определить сопряжение f &&& g : C → A × B так, чтобы fst ∘ (f &&& g) = f и аналогично для g . Параметричность гарантирует универсальные свойства автоматически, и мой менее тонкий выбор имен должен дать вам представление.
(&&&)
Оператор определен вControl.Arrow
, между прочим.Двойственным из вышеперечисленного является побочный продукт A + B с инъекциями inl : A → A + B и inr : B → A + B, где для любого типа C и функций f : A → C, g : B → C вы можете определить сопряжение f ||| g : A + B → C такое, что имеют место очевидные эквивалентности. Опять же, параметричность гарантирует большинство сложных деталей автоматически. В этом случае стандартные инъекции - это просто,
Left
аRight
сопряжение - это функцияeither
.Многие из свойств типа продукта и суммы могут быть получены из вышеупомянутого. Обратите внимание, что любой одноэлементный тип является конечным объектом Hask, а любой пустой тип является начальным объектом.
Возвращаясь к вышеупомянутой отсутствующей операции, в декартовой закрытой категории у вас есть экспоненциальные объекты, которые соответствуют стрелкам категории. Наши стрелки являются функциями, наши объекты являются типами с родом
*
, и типA -> B
действительно ведет себя как B A в контексте алгебраической манипуляции с типами. Если неясно, почему это так, рассмотрите типBool -> A
. С только два возможных входных данных, функция такого типа изоморфна двум значениям типаA
, то есть(A, A)
. ИбоMaybe Bool -> A
у нас есть три возможных входа и так далее. Кроме того, обратите внимание, что если мы перефразируем приведенное выше определение сопряжения для использования алгебраической нотации, мы получим тождество C A × C B = CА + В .Что касается того, почему все это имеет смысл - и, в частности, почему использование расширения степенных рядов оправдано, - обратите внимание, что большая часть вышеперечисленного относится к «обитателям» типа (т. Е. К различным значениям, имеющим этот тип) в порядке продемонстрировать алгебраическое поведение. Чтобы сделать эту перспективу явной:
Тип продукта
(A, B)
представляет собой значение каждого изA
иB
, взятых независимо. Таким образом, для любого фиксированного значенияa :: A
существует одно значение типа(A, B)
для каждого обитателяB
. Это, конечно, декартово произведение, а число жителей типа продукта является произведением числа жителей факторов.Тип сумма
Either A B
представляет значение из любогоA
илиB
, с левой и правой ветви отличаются. Как упоминалось ранее, это несвязанный союз, а число жителей типа суммы является суммой числа жителей слагаемых.Экспоненциальный тип
B -> A
представляет собой отображение значений типаB
на значения типаA
. Для любого фиксированного аргумента ему может быть присвоеноb :: B
любое значениеA
; значение типаB -> A
выбирает одно такое отображение для каждого входа, что эквивалентно произведением как можно большее число копий ,A
какB
есть жители, отсюда экспоненциация.Хотя вначале заманчиво рассматривать типы как наборы, на самом деле это не очень хорошо работает в этом контексте - мы имеем несвязанное объединение, а не стандартное объединение множеств, нет очевидной интерпретации пересечения или многих других операций над множествами, и мы обычно не заботится о членстве в наборе (оставляя это проверке типов).
С другой стороны, приведенные выше конструкции тратят много времени на подсчет жителей, и перечисление возможных значений типа является здесь полезной концепцией. Это быстро приводит нас к перечислительной комбинаторике , и если вы обратитесь к связанной статье в Википедии, вы обнаружите, что первое, что она делает, - это определение «пар» и «союзов» в том же смысле, что и для типов товаров и сумм посредством генерируя функции , затем делает то же самое для «последовательностей», которые идентичны спискам в Haskell, используя точно ту же технику, что и вы.
Редактировать: О, и вот быстрый бонус, который, я думаю, демонстрирует суть поразительно. Вы упомянули в комментарии, что для типа дерева
T = 1 + T^2
вы можете получить идентичностьT^6 = 1
, что явно неверно. Однако этоT^7 = T
действительно так , и биекция между деревьями и семью корнями деревьев может быть построена напрямую, ср. Андреас Бласс "Семь деревьев в одном" .Редактировать × 2: В отношении конструкции «производного типа», упомянутой в других ответах, вам также может понравиться эта статья того же автора, которая в дальнейшем опирается на эту идею, включая понятия деления и другие интересные вещи.
источник
Двоичные деревья определяются уравнением
T=1+XT^2
в полукольце типов. По построениюT=(1-sqrt(1-4X))/(2X)
определяется тем же уравнением в полукольце комплексных чисел. Итак, учитывая, что мы решаем одно и то же уравнение в одном и том же классе алгебраической структуры, на самом деле не должно удивлять, что мы видим некоторое сходство.Подвох в том, что когда мы размышляем о полиномах в полукольце комплексных чисел, мы обычно используем тот факт, что комплексные числа образуют кольцо или даже поле, поэтому мы используем такие операции, как вычитание, которые не применяются к полукольцам. Но мы часто можем исключить вычитания из наших аргументов, если у нас есть правило, которое позволяет нам отменять обе части уравнения. Такого рода вещи доказали Фиоре и Ленстер, показывающие, что многие аргументы о кольцах можно перенести на полукольца.
Это означает, что многие ваши математические знания о кольцах могут быть надежно перенесены в типы. В результате некоторые аргументы, включающие комплексные числа или степенные ряды (в кольце формальных степенных рядов), могут переноситься на типы совершенно строгим образом.
Однако это еще не все. Одно дело доказать, что два типа равны (скажем), показав, что два степенных ряда равны. Но вы также можете получить информацию о типах, проверив термины в степенных рядах. Я не уверен, каким должно быть официальное заявление здесь. (Рекомендую Brent Йорг в бумагу на комбинаторных видах для некоторой работы , которая тесно связана , но виды не такие же , как типы.)
То, что я нахожу совершенно невероятным, - это то, что вы обнаружили, можно распространить на исчисление. Теоремы об исчислении можно перенести на полукольцо типов. Фактически, даже аргументы о конечных разностях могут быть перенесены, и вы обнаружите, что классические теоремы из численного анализа имеют интерпретации в теории типов.
Радоваться, веселиться!
источник
P = X^2
имеет производнуюdP = X + X
,Either
как и контекст с одной дырой в паре. Это круто. Мы могли бы «интегрировать»,Either
чтобы получить пару тоже. Но если мы пытаемся «интегрировать»Maybe
(с типомM = 1 + X
), то нам нужно иметь\int M = X + X^2 / 2
что-то бессмысленное (что такое половина типа?). Означает ли это, чтоMaybe
это не контекст с одним отверстием любого другого типа?(A,A)
с отверстием в немA
и немного говорит вам, с какой стороны находится отверстие. УA
одинокого нет выделенной дыры для заполнения, поэтому вы не можете «интегрировать» его. Тип недостающей информации в этом случае, конечно же ,2
.X^2/2
blog.sigfpe.com/2007/09/type-of-distinct-pairs.htmlКажется, что все, что вы делаете, - это расширение отношения повторения.
А поскольку правила для операций над типами работают так же, как правила для арифметических операций, вы можете использовать алгебраические средства, чтобы помочь вам выяснить, как расширить рекуррентное отношение (поскольку это не очевидно).
источник
X
что это элемент действительных чисел, к истинному утверждению о типах, и, более того, где это соответствует (коэффициентn
степени й степени) <=> (число из типов удерживающихn
элементов) откуда?T = 1 + T^2
) можно вывестиT^6 = 1
(т.е. решенияx^2 - x + 1 = 0
являются шестой корни из единицы) , но это явно не верно , что тип продукт , состоящий из шести двоичных деревьев эквивалентна единице()
.T^7
T
L = 1 + X * L
него, лучше было бы то же самое, что вы получаете, когда вы расширяете серию, последовательностью. В противном случае вы можете запустить результат в обратном направлении, чтобы получить что-то неверное о реалах.У меня нет полного ответа, но эти манипуляции имеют тенденцию «просто работать». Соответствующей статьей может быть « Объекты категорий как комплексные числа» Фьоре и Ленстера - я наткнулся на эту статью, читая блог sigfpe по соответствующей теме ; остальная часть этого блога - золотая жила для подобных идей и стоит проверить!
Кстати, вы также можете различать типы данных - это даст вам подходящую застежку-молнию для этого типа данных!
источник
Алгебра коммуникативных процессов (ACP) имеет дело с подобными выражениями для процессов. Он предлагает сложение и умножение в качестве операторов выбора и последовательности со связанными нейтральными элементами. На основании этого есть операторы для других конструкций, таких как параллелизм и нарушение. См. Http://en.wikipedia.org/wiki/Algebra_of_Communicating_Processes . В Интернете также есть статья под названием «Краткая история алгебры процессов».
Я работаю над расширением языков программирования с помощью ACP. В апреле прошлого года я представил исследовательский документ на Scala Days 2012, доступный по адресу http://code.google.com/p/subscript/.
На конференции я продемонстрировал отладчик, выполняющий параллельную рекурсивную спецификацию пакета:
Сумка = A; (Сумка & а)
где А и стенд для ввода и вывода действий; точка с запятой и амперсанд означают последовательность и параллелизм. Смотрите видео на SkillsMatter, доступное по предыдущей ссылке.
Спецификация сумки более сопоставима с
L = 1 + X • L
было бы
B = 1 + X & B
ACP определяет параллелизм с точки зрения выбора и последовательности с использованием аксиом; см. статью в Википедии. Интересно, какова будет аналогия с сумкой?
L = 1 / (1-X)
Программирование в стиле ACP удобно для анализаторов текста и контроллеров графического интерфейса. Технические характеристики, такие как
searchCommand = clicked (searchButton) + клавиша (Enter)
cancelCommand = clicked (cancelButton) + клавиша (Escape)
можно записать более кратко, сделав два уточнения «нажатыми» и «ключами» неявными (например, что Scala позволяет с функциями). Следовательно, мы можем написать:
searchCommand = searchButton + Enter
cancelCommand = cancelButton + Escape
Правые части теперь содержат операнды, которые являются данными, а не процессами. На этом уровне нет необходимости знать, какие неявные уточнения превратят эти операнды в процессы; они не обязательно уточняют входные действия; выходные действия также будут применяться, например, в спецификации тестового робота.
Процессы получают таким образом данные в качестве компаньонов; таким образом, я использую термин «алгебра предметов».
источник
Серия исчисления и маклаурина с типами
Вот еще одно небольшое добавление - комбинаторное понимание того, почему коэффициенты в разложении рядов должны «работать», в частности, сосредоточение внимания на рядах, которые могут быть получены с использованием подхода Тейлора-Маклорина из исчисления. NB: пример расширения серии, который вы приводите для типа манипулируемого списка, - это серия Maclaurin.
Поскольку другие ответы и комментарии касаются поведения выражений алгебраического типа (сумм, произведений и показателей степени), этот ответ исключит эти детали и сосредоточится на типе «исчисление».
Вы можете заметить, что в этом ответе кавычки делают тяжелую работу. Есть две причины:
Определение серии Маклаурин
Ряд Маклорена функции
f : ℝ → ℝ
определяется какгде
f⁽ⁿ⁾
означаетn
производную отf
.Чтобы понять смысл ряда Маклаурина как интерпретируемого с типами, нам нужно понять, как мы можем интерпретировать три вещи в контексте типов:
0
(1/n!)
и оказывается, что эти концепции из анализа имеют подходящих аналогов в мире типов.
Что я имею в виду под «подходящим партнером»? Он должен иметь вид изоморфизма - если мы можем сохранить истину в обоих направлениях, факты, выводимые в одном контексте, могут быть перенесены в другой.
Исчисление с типами
Так что же означает производная выражения типа? Оказывается, что для большого и корректного («дифференцируемого») класса выражений типов и функторов существует естественная операция, которая ведет себя достаточно схожим образом, чтобы быть подходящей интерпретацией!
Чтобы испортить изюминку, операция, аналогичная дифференциации, заключается в создании «контекстов с одним отверстием». Это отличное место для дальнейшего раскрытия этого конкретного вопроса, но основная концепция контекста с одним отверстием (
da/dx
) заключается в том, что он представляет собой результат выделения отдельного подпункта определенного типа (x
) из термина (типаa
), сохраняя вся другая информация, в том числе та, которая необходима для определения исходного местоположения подпункта. Например, один из способов представления контекста с одним отверстием для списка - два списка: один для элементов, которые были до извлеченного, и один для элементов, следующих за.Мотивация для идентификации этой операции с дифференцированием исходит из следующих наблюдений. Мы пишем
da/dx
для обозначения типа контекстовa
с одним отверстием для типа с отверстием типаx
.Здесь
1
и0
представляют типы с ровно одним и ровно нулевым населением соответственно,+
а также×
представляют суммы и типы продуктов, как обычно.f
иg
используются для представления функций типа или формирователей выражений типа, и[f(x)/a]
означает операцию заменыf(x)
для каждогоa
в предыдущем выражении.Это может быть написано в стиле без точек, написав,
f'
чтобы означать производную функцию функции типаf
, таким образом:который может быть предпочтительным.
Обратите внимание, что равенства можно сделать строгими и точными, если мы определим производные с использованием классов изоморфизма типов и функторов.
Теперь отметим, в частности, что правила в исчислении, относящиеся к алгебраическим операциям сложения, умножения и композиции (часто называемые правилами сумм, произведений и цепочек), отражаются именно операцией «создания дыры». Кроме того, базовые случаи «создания дыры» в константном выражении или сам термин
x
также ведут себя как дифференцирование, поэтому по индукции мы получаем дифференцирующее поведение для всех выражений алгебраического типа.Теперь мы можем интерпретировать дифференцирование, что означает
n
«производная» выражения типаdⁿe/dxⁿ
? Это тип, представляющийn
контексты-места: термины, которые при «заполнении»n
терминами типаx
приводят кe
. Есть еще одно ключевое наблюдение, связанное с(1/n!)
«приходом позже».Инвариантная часть функтора типа: применение функции к 0
У нас уже есть интерпретация для
0
мира типов: пустой тип без членов. Что это означает, с комбинаторной точки зрения, применить к нему функцию типа? Говоря более конкретно, предположим, чтоf
это функция типа, как онаf(0)
выглядит? Ну, у нас, конечно, нет доступа ни к чему типу0
, поэтому любые конструкции, дляf(x)
которых требуетсяx
, недоступны. Остаются те термины, которые доступны при их отсутствии, которые мы можем назвать «инвариантной» или «постоянной» частью типа.Для явного примера возьмем
Maybe
функтор, который может быть представлен алгебраически какx ↦ 1 + x
. Когда мы применяем это к0
, мы получаем1 + 0
- это как1
: единственно возможное значение - этоNone
значение. Для списка, аналогично, мы получаем только термин, соответствующий пустому списку.Когда мы возвращаем его и интерпретируем тип
f(0)
как число, его можно рассматривать как подсчет того, сколько терминов типаf(x)
(для любогоx
) можно получить без доступа кx
: то есть числу «пустых» терминов ,Собираем все вместе: полная интерпретация серии Маклаурин
Боюсь, я не могу думать о соответствующей прямой интерпретации
(1/n!)
как о типе.Однако если мы рассмотрим тип
f⁽ⁿ⁾(0)
в свете вышесказанного, то увидим, что его можно интерпретировать как типn
контекстов места для термина типа,f(x)
который еще не содержитx
- то есть, когда мы «интегрируем» ихn
раз результирующий член имеет ровноn
x
s, не больше, не меньше. Тогда интерпретация типаf⁽ⁿ⁾(0)
как числа (как в коэффициентах ряда Маклауринаf
) представляет собой просто подсчет количества таких пустыхn
контекстов. Мы почти у цели!Но где это
(1/n!)
заканчивается? Изучение процесса типа «дифференцирование» показывает нам, что при многократном применении он сохраняет «порядок», в котором извлекаются подтермы. Например, рассмотрим термин(x₀, x₁)
«тип»x × x
и операцию «проделывание дыры» в нем дважды. Мы получаем обе последовательностихотя оба они имеют один и тот же термин, потому что есть
2! = 2
способы взять два элемента из двух, сохраняя порядок. В общем, естьn!
способы взятьn
элементы изn
. Таким образом, чтобы подсчитать количество конфигураций типа функтора, которые имеютn
элементы, мы должны посчитать типf⁽ⁿ⁾(0)
и поделитьn!
, точно так же, как в коэффициентах ряда Маклаурина.Таким образом, деление на
n!
оказывается интерпретируемым просто как само по себе.Заключительные мысли: «рекурсивные» определения и аналитичность
Сначала несколько замечаний:
Поскольку у нас есть правило цепочки, мы можем использовать неявное дифференцирование , если формализуем производные типа как классы изоморфизма. Но неявное дифференцирование не требует никаких чужих маневров, таких как вычитание или деление! Таким образом, мы можем использовать его для анализа определений рекурсивных типов. Чтобы взять пример вашего списка, у нас есть
и тогда мы можем оценить
получить коэффициент
X¹
в ряду Маклаурина.Но так как мы уверены, что эти выражения действительно строго «дифференцируемы», хотя бы неявно, и поскольку мы имеем соответствие с функциями ℝ → ℝ, где производные, безусловно, уникальны, мы можем быть уверены, что даже если мы получим значения, используя незаконные операции, результат действителен.
Теперь аналогично, чтобы использовать второе наблюдение, из-за соответствия (это гомоморфизм?) Функциям ℝ → ℝ, мы знаем, что, если мы удовлетворены тем, что функция имеет ряд Макларина, если мы можем найти любой ряд в все , принципы, изложенные выше, могут быть применены, чтобы сделать его строгим.
Что касается вашего вопроса о композиции функций, я полагаю, что правило цепочки дает частичный ответ.
Я не уверен, к какому числу ADT в стиле Haskell это относится, но я подозреваю, что их много, если не все. Я нашел поистине изумительное доказательство этого факта, но этот запас слишком мал, чтобы его содержать ...
Теперь, конечно, это только один способ выяснить, что здесь происходит, и, возможно, есть много других способов.
Резюме: TL; DR
0
дает нам «пустые» термины для этого функтора.источник
Теория зависимого типа и функции произвольного типа
Мой первый ответ на этот вопрос был высоким по понятиям и низким по деталям и отразился на подвопросе «что происходит?»; этот ответ будет таким же, но сфокусирован на вопросе: «можем ли мы получить функции произвольного типа?».
Одним из расширений алгебраических операций суммы и произведения являются так называемые «большие операторы», которые представляют сумму и произведение последовательности (или, в более общем смысле, сумму и произведение функции над областью), обычно записываемые
Σ
иΠ
соответственно. Смотрите сигма нотации .Итак, сумма
может быть написано
где
a
некоторая последовательность действительных чисел, например. Продукт будет представлен аналогичноΠ
вместоΣ
.Когда вы смотрите издалека, этот вид выражения во многом похож на «произвольную» функцию
X
; Конечно, мы ограничены выразимыми рядами и связанными с ними аналитическими функциями. Является ли это кандидатом на представление в теории типов? Определенно!Класс теорий типов, которые непосредственно представляют эти выражения, является классом теорий «зависимых» типов: теорий с зависимыми типами. Естественно, у нас есть термины, зависящие от терминов, и в таких языках, как Haskell, с функциями типов и определением типов, терминами и типами в зависимости от типов. В зависимой настройке у нас также есть типы в зависимости от условий. Haskell не является языком с зависимой типизацией, хотя многие свойства зависимых типов могут быть смоделированы с помощью некоторой пытки языка .
Карри-Ховард и зависимые типы
«Изоморфизм Карри-Говарда» начал свою жизнь как наблюдение, что термины и правила оценки типов лямбда-исчисления с простыми типами в точности соответствуют естественному дедукции (сформулированной Генценом), примененной к интуиционистской логике высказываний, с типами, заменяющими суждения и термины, занимающие место доказательств, несмотря на то, что оба были изобретены / открыты независимо. С тех пор это стало огромным источником вдохновения для теоретиков типов. Одна из наиболее очевидных вещей, которую следует рассмотреть, - может ли и как это соответствие для логики высказываний быть распространено на логику предикатов или логики более высокого порядка. Теории зависимого типа изначально возникли на этом пути исследования.
Для ознакомления с изоморфизмом Карри-Ховарда для простейшего типа лямбда-исчисления см. Здесь . Например, если мы хотим доказать,
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
. Аналогично для∃
.Комбинаторные соображения: продукты и суммы
Наряду с соответствием типов по Карри-Говарду с предложениями мы имеем комбинаторное соответствие алгебраических типов с числами и функциями, что является основным вопросом этого вопроса. К счастью, это можно распространить на зависимые типы, описанные выше!
Я буду использовать обозначение модуля
представить «размер» типа
A
, сделать явным соответствие, обозначенное в вопросе, между типами и числами. Обратите внимание, что это понятие вне теории; Я не утверждаю, что в языке должен быть такой оператор.Давайте посчитаем возможные (полностью редуцированные, канонические) члены типа
который является типом зависимых функций, принимающих термины
x
типаX
к терминам типаP(x)
. Каждая такая функция должна иметь вывод для каждого членаX
, и этот вывод должен быть определенного типа. Для каждогоx
дюймаX
, то это дает|P(x)|
«выбор» вывод.Изюминка
что, конечно, не имеет большого смысла, если
X
естьIO ()
, но применимо к алгебраическим типам.Точно так же термин типа
тип пар
(x, p)
сp : P(x)
, так что для любогоx
вX
можно построить соответствующую пару с любым членомP(x)
, давая|P(x)|
«выбор».Следовательно,
с такими же предостережениями.
Это оправдывает общее обозначение зависимых типов в теориях, использующих символы,
Π
иΣ
, действительно, многие теории стирают различие между «для всех» и «продуктом» и между «есть» и «суммой» из-за вышеупомянутых соответствий.Мы приближаемся!
Векторы: представление зависимых кортежей
Можем ли мы теперь кодировать числовые выражения, такие как
как выражения типа?
Не совсем. Хотя мы можем неофициально рассмотреть значение выражений, таких как
Xⁿ
в Haskell, гдеX
это тип иn
натуральное число, это злоупотребление нотацией; это выражение типа, содержащее число: явно не является допустимым выражением.С другой стороны, с зависимыми типами на картинке, типы, содержащие числа, это как раз и есть точка; на самом деле, зависимые кортежи или «векторы» являются очень часто цитируемым примером того, как зависимые типы могут обеспечить прагматическую безопасность на уровне типов для таких операций, как доступ к списку . Вектор - это просто список вместе с информацией на уровне типов относительно его длины: именно то, что нам нужно для подобных выражений типа
Xⁿ
.Для продолжительности этого ответа, пусть
быть типом
n
векторовX
длины значений -type.Технически
n
здесь, а не фактическое натуральное число, представление в системе натурального числа. Мы можем представлять натуральные числа (Nat
) в стиле Пеано как ноль (0
) или как преемник (S
) другого натурального числа, иn ∈ ℕ
я пишу˻n˼
для обозначения термина, вNat
котором он представленn
. Например,˻3˼
естьS (S (S 0))
.Тогда у нас есть
для любого
n ∈ ℕ
.Типы Nat: продвижение ℕ терминов в типы
Теперь мы можем кодировать выражения как
как типы. Это конкретное выражение приведет к типу, который, конечно, изоморфен типу списков
X
, как указано в вопросе. (Не только это, но и с точки зрения теории категорий, функция типа - которая является функтором - переходX
к указанному выше типу естественным образом изоморфна функтору List.)Последний фрагмент головоломки для «произвольных» функций - это как
выражения как
так что мы можем применить произвольные коэффициенты к степенному ряду.
Мы уже понимаем соответствие алгебраических типов числам, что позволяет нам сопоставлять типы с числами и функции типов с числовыми функциями. Мы также можем пойти другим путем! - если взять натуральное число, то, очевидно, существует определимый алгебраический тип с таким количеством членов-членов, независимо от того, есть у нас зависимые типы или нет. Мы можем легко доказать это вне теории типов по индукции. Нам нужен способ отображения натуральных чисел на типы внутри системы.
Приятное осознание состоит в том, что, когда у нас есть зависимые типы, доказательство по индукции и построение по рекурсии становятся очень похожими - на самом деле, во многих теориях это одно и то же. Поскольку мы можем по индукции доказать, что существуют типы, которые удовлетворяют нашим потребностям, разве мы не можем их построить?
Существует несколько способов представления типов на уровне терминов. Я буду использовать здесь воображаемую нотацию по Хаскеллу
*
для вселенной типов, которая обычно считается типом в зависимом окружении. 1Аналогичным образом, существует также как минимум столько же способов обозначения «
ℕ
исключения», сколько существует теорий зависимых типов. Я буду использовать Haskellish для сопоставления с образцом.Нам необходимо отображение,
α
отNat
к*
, со свойствомДостаточно следующего псевдодетерминации.
Итак, мы видим, что действие
α
отражает поведение преемникаS
, делая его своего рода гомоморфизмом.Successor
является функцией типа, которая «добавляет единицу» к числу членов типа; то есть|Successor a| = 1 + |a|
для любогоa
с определенным размером.Например
α ˻4˼
(что естьα (S (S (S (S 0))))
), этои условия этого типа
давая нам точно четыре элемента:
|α ˻4˼| = 4
.Аналогично, для любого
n ∈ ℕ
, у нас естькак требуется.
*
были просто представителями типов, а операция предоставляется как явное отображение терминов типа*
на связанные с ними типы. Другие теории допускают, чтобы сами буквальные типы были сущностями уровня термина.«Произвольные» функции?
Теперь у нас есть аппарат для выражения общего общего степенного ряда в виде типа!
Сериал
становится типом
где
˻f˼ : Nat → Nat
некоторое подходящее представление на языке функцииf
. Мы можем видеть это следующим образом.Насколько это «произвольно»? Этот метод ограничен не только целыми коэффициентами, но и натуральными числами. Помимо этого,
f
может быть что угодно, учитывая язык Тьюринга, полный с зависимыми типами, мы можем представить любую аналитическую функцию с натуральными числовыми коэффициентами.Я не исследовал взаимодействие этого, например, с случаем, представленным в вопросе о
List X ≅ 1/(1 - X)
том, какой возможный смысл могут иметь такие отрицательные и нецелые «типы» в этом контексте.Надеюсь, этот ответ каким-то образом исследует, как далеко мы можем зайти с функциями произвольного типа.
источник