Форум программистов, компьютерный форум, киберфорум
Mysterious Light
Войти
Регистрация
Восстановить пароль
Блоги Сообщество Поиск  

Эссе. Парование. Часть 3. Теория типов

Запись от Mysterious Light размещена 25.08.2013 в 23:56
Показов 2856 Комментарии 0

Главная запись: https://www.cyberforum.ru/blog... g1562.html

Параллелизм данных
Имея объект https://www.cyberforum.ru/cgi-bin/latex.cgi?a, можно параллельно вычислять https://www.cyberforum.ru/cgi-bin/latex.cgi?x=f(a) и https://www.cyberforum.ru/cgi-bin/latex.cgi?y=g(a), поэтому такие угловые скобочки спаривания https://www.cyberforum.ru/cgi-bin/latex.cgi?\langle f,g\rangle можно мыслить как маркер к фразе «функция параллельного вычисления https://www.cyberforum.ru/cgi-bin/latex.cgi?f и https://www.cyberforum.ru/cgi-bin/latex.cgi?g на общем аргументе». В этом прелесть параллелизма данных: в коде программы мы ни слова не пишем о том, что что-то нужно параллелить, а оно само сделается.
Аналогично, функторное произведение https://www.cyberforum.ru/cgi-bin/latex.cgi?\left[f,g\right] обозначает функцию, которой не нужно знать целиков весь свой аргумент, чтобы начать вычисляться. Например, пусть https://www.cyberforum.ru/cgi-bin/latex.cgi?x и https://www.cyberforum.ru/cgi-bin/latex.cgi?y — два объекта, которые формируют пару как аргумент для этой функции, причём https://www.cyberforum.ru/cgi-bin/latex.cgi?y вычисляется/формирует дольше, чем https://www.cyberforum.ru/cgi-bin/latex.cgi?x. Если при этом https://www.cyberforum.ru/cgi-bin/latex.cgi?g(y) вычисляется быстрее, чем https://www.cyberforum.ru/cgi-bin/latex.cgi?f(x), то имеет смысл начать вычислять https://www.cyberforum.ru/cgi-bin/latex.cgi?f(x) как только https://www.cyberforum.ru/cgi-bin/latex.cgi?x будет готов. Безусловно, программист может позаботиться об этом самостоятельно и не вводить https://www.cyberforum.ru/cgi-bin/latex.cgi?\left[f,g\right], а работать и ними в двух разных потоках, но зачем это делать, если компилятор может самостоятельно догадаться, что здесь возможно параллельное вычисление. Таким образом оптимизация произойдёт самостоятельно, а программист будет просто писать так, как ему удобнее.

Теория типов и лямбда-исчисление
Принципиальное отличие типа от множества заключается в том, что множество «знает» о своих элементах, а тип — нет. Тип — это всего лишь маркер, который ставится на объекты для того, чтобы они не попали в «чужой» контекст, чтобы функция не вызвалась на объекте, который не может быть её аргументом. Кроме этого, в ТТ аргументом и значением функции может быть объект любого допустимого типа, в т.ч. другие функции. Так, возможен тип https://www.cyberforum.ru/cgi-bin/latex.cgi?(A\to B)\to(C\to D), описывающий функцию, отображающую функцию https://www.cyberforum.ru/cgi-bin/latex.cgi?A\to B в функцию https://www.cyberforum.ru/cgi-bin/latex.cgi?C\to D. Таким образом функция — это и объект, и значение, и алгоритм, и правило одновременно.

Каррирование
Понимание пары базируется на том, где чаще всего в программировании используется «два объекта» — на двухаргументных функциях. Действительно, тяжело себе представить, каково было бы программирование, если бы нельзя использовать двух и более аргументные функции и конструкторы. Тем не менее есть один способ, позволяющий обойти это ограничение. Называется каррирование и заключается в переходе от функции https://www.cyberforum.ru/cgi-bin/latex.cgi?XY\to C к функции https://www.cyberforum.ru/cgi-bin/latex.cgi?X\to(Y\to C).
Haskell
1
2
3
4
curry :: ((x,y) -> c) -> x -> y -> c
curry f = \x y -> f (x,y)
-- или
curry f x y = f (x,y)
JavaScript
1
2
3
4
5
6
7
8
9
10
11
function curry(f) {
    return function(x) {
        return function(y) {
            return f(x,y);
        };
    };
}
 
function add(x,y) { return x+y; }
var inc = curry(add)(1);
inc(2) == 3 // true
Дадим первое определение:
Декартовое произведение типов https://www.cyberforum.ru/cgi-bin/latex.cgi?X и https://www.cyberforum.ru/cgi-bin/latex.cgi?Y — это некоторый тип https://www.cyberforum.ru/cgi-bin/latex.cgi?XY и обратимая функция https://www.cyberforum.ru/cgi-bin/latex.cgi?\operatorname{curry}: (XY\to C) \to (X\to (Y\to C)). Слово «обратимая» означает, что существует функция https://www.cyberforum.ru/cgi-bin/latex.cgi?\operatorname{uncurry}: (X\to (Y\to C)) \to (XY\to C), которая в композиции с curry даёт идентичное отображение. Говоря ТК языком, curry — это изоморфизм в категории типов.
Это определение даёт представление, зачем нужны пары, а именно для того, чтобы переходить от двухаргументных (точнее от каскада) функций к одноаргументной, причём в этом одном аргументе содержится информация сразу про два аргумента. Недостаток также очевиден: определение неконструктивно; не понятно, как построить такой тип и как по двум аргументам построить их пару.

По аналогии с парованием функций в ТК можно потребовать существование функции (точнее, либо семейства функций, либо одну слабо-полиморфную)
https://www.cyberforum.ru/cgi-bin/latex.cgi?\rm{fpair} \; : \; (A \to X) \to (A \to Y) \to (A \to XY)
В результате мы получим то, что было получено в ТК, только для категории типов. Поэтому следует поискать другое определение.
Прим.: Функция https://www.cyberforum.ru/cgi-bin/latex.cgi?\rm{fpair} имеет тип-параметр A, а потому нужно или продублировать fpair для всех типов, вроде fpairInt, fpairDouble, то есть рассматривать fpair как много overloaded функций, либо сказать, что A является типом-аргументом.

Определение в системе с полиморфизмом
Решим эту проблему, дав неэквивалентное второе определение:
https://www.cyberforum.ru/cgi-bin/latex.cgi? XY \equiv \forall c. (X\to (Y\to c)) \to c.
Понимать это нужно так: пусть есть два объекта https://www.cyberforum.ru/cgi-bin/latex.cgi?x и https://www.cyberforum.ru/cgi-bin/latex.cgi?y. Всякая двухаргументная (каскадная) функция https://www.cyberforum.ru/cgi-bin/latex.cgi?g принимает значение https://www.cyberforum.ru/cgi-bin/latex.cgi?gxy\equiv (g(x))(y) типа c. Поэтому объекты https://www.cyberforum.ru/cgi-bin/latex.cgi?x и https://www.cyberforum.ru/cgi-bin/latex.cgi?y порождают функционал https://www.cyberforum.ru/cgi-bin/latex.cgi?\lambda g.gxy, который и является парой в смысле последнего определения.
https://www.cyberforum.ru/cgi-bin/latex.cgi?(x,y) := \lambda g.gxy
Мы можем взять функции https://www.cyberforum.ru/cgi-bin/latex.cgi?\lambda x.\lambda y.x и https://www.cyberforum.ru/cgi-bin/latex.cgi?\lambda x.\lambda y.y и передать их в качестве аргумента функционалу. Ожидаемо, мы получим назад https://www.cyberforum.ru/cgi-bin/latex.cgi?x и https://www.cyberforum.ru/cgi-bin/latex.cgi?y соответственно: https://www.cyberforum.ru/cgi-bin/latex.cgi?(\lambda g. gxy)(\lambda x\lambda y.x) = x. Поэтому эти две функции порождают проекции, уже известные нам из прошлых разделов. Точнее, проекции задаются так:
https://www.cyberforum.ru/cgi-bin/latex.cgi?pr_1 = \lambda p. p(\lambda x\lambda y.x)
https://www.cyberforum.ru/cgi-bin/latex.cgi?pr_2 = \lambda p. p(\lambda x\lambda y.y)
Несложно убедиться, что curry и uncurry выражаются через две проекции и конструктор:
https://www.cyberforum.ru/cgi-bin/latex.cgi?\operatorname{curry} = \lambda f\lambda x\lambda y. f(x,y),
https://www.cyberforum.ru/cgi-bin/latex.cgi?\operatorname{uncurry} = \lambda f\lambda p. f (pr_1p) (pr_2p).

Этот подход при всей своей красоте оказывается очень требовательным: он требует возможности передавать в качестве аргумента функцию с заранее неизвестным типом. Этот тип https://www.cyberforum.ru/cgi-bin/latex.cgi?c неизвестен до того, как функция https://www.cyberforum.ru/cgi-bin/latex.cgi? XY \equiv \forall c. (X\to (Y\to c)) \to c будет применена к функции-аргументу, тип которой известен, а потому тип c определится из аргумента. В определённом смысле это выглядит как generic; нельзя сказать, что c это тип-пустышка, прародитель всех типов, подобно Object в большинстве ЯП. Это скорее параметр функции, его типовый аргумент. Аналогия хорошо усматривается: подобно тому, как в функции https://www.cyberforum.ru/cgi-bin/latex.cgi?\lambda x.x+1 сам (т.н. формальный) аргумент не имеет определённого значения, является подстановочным местом для реального т.н. актуального аргумента, которое определяется во время применения функции к актуальному аргументу, здесь тип c играет ту же роль. Поэтому в некоторых нотациях (характерно для явнотипизированных aka Черчевых систем, неявнотипизированным системам aka типизации Карри это лишнее) типовый абстрактор пишется явно. Сравните:
https://www.cyberforum.ru/cgi-bin/latex.cgi?(\Lambda\alpha.\lambda x:\alpha.x) \; : \; \forall\alpha. \alpha\to\alpha
https://www.cyberforum.ru/cgi-bin/latex.cgi?\lambda x: \rm{Int}. x \; : \; \rm{Int} \to \rm{Int}
В первом случае тип https://www.cyberforum.ru/cgi-bin/latex.cgi?\alpha является подстановочным местом для произвольного типа, в то время как тип во втором выражении конкретен. Как уже было упомянуто, в системах с неявной типизацией абстрактор по типу https://www.cyberforum.ru/cgi-bin/latex.cgi?\Lambda в самом терме не пишется, указывается только абстракция https://www.cyberforum.ru/cgi-bin/latex.cgi?\forall в типе терма. Системы, в которых допускается такой вид абстракции — абстрагирование терма от типа, — называются системами с полиморфизмом.
JavaScript
1
2
3
4
5
6
7
8
function pairUncurry(x,y) { return function(g) { return g(x,y); }; }
function pair(x) { return function(y) { return function(g) { return g(x)(y); }; }; }
var projectX = curry(function(x,y) { return x; }); // чтоб понятнее было
var projectY = curry(function(x,y) { return y; }); // написано привычном виде
 
var p12 = pair(1)(2);
p12(projectX) + p12(projectY) == 3 // true
p12(curry(add)) == 3 // true
Выводы
Кратко о рассказанном:
1. Два конструктивных определения, ТМ и ТТ.
2. Два неконструктивных, но полезных определения, ТК и ТТ (неполноценное).
3. Спаривание функций, с общим аргументом и с независимыми.
4. Рассуждения об автоматическом распараллеливании.
5. Терминал и элементы, ТК описание типичных функций.
6. Демонстрация на языках JS, Haskell и Java.
Размещено в Структуры данных
Надоела реклама? Зарегистрируйтесь и она исчезнет полностью.
Всего комментариев 0
Комментарии
 
Новые блоги и статьи
Беседа с ИИ о программистах, недопускающих к созданию и правке кода генеративные ИИ и причины этого
zorxor 21.09.2026
Раньше я радовался или получал некоторые эмоции, пусть небольшие, но всё же, от самого процесса написания кода, рекомпиляции и запуска, видя постепенное развитие программы и прочее. А теперь лень. . .
Мобильное приложение ColorStep
pavlinmavlin 17.09.2026
Реализовал приложение Красный, Зеленый, Синий в Unity3d + c#. Название изменил на ColorStep. Приложение прошло модерацию и теперь доступно для скачивания. Делал его сам, шаг за шагом — и вот,. . .
Запрет дублирования строк в табличной части
Maks 13.09.2026
Реализация из решения ниже выполнена на нетиповом справочнике "Нормы ТО" с табличной часть "Виды ТО", разработанного в КА2, со следующими реквизитами: - ВидТО (СправочникСсылка. ВидыТО); - ВидГСМ. . .
Скрипты Tampermonkey для CyberForum, ChatGPT, Claude и пр.
Jin X 06.09.2026
Скрипты Tampermonkey для CyberForum, ChatGPT, Claude и пр. Работая с форумом и нейросетями в браузере часто хочется что-то подкорректировать или добавить какого-то функционала. Ниже прикреплён. . .
Программа опроса у.з. расходомера SLS-720F
Argus19 02.09.2026
Программа опроса у. з. расходомера SLS-720F Программа опрашивает один раз в минуту три ультразвуковых расходомера SLS-720F через интерфейс RS-485 по протоколу Modbus RTU. Опрашиваются регистры. . .
Hyper-V: Компьютер должен поддерживать доверенный платформенный модуль 2.0.
Maks 31.08.2026
При установке Windows 11 на виртуальную машину Hyper-V 2-го поколения вылезла такая ошибка: Решение: в параметрах виртуальной машины, в разделе "Безопасность" (Security) активировать флаг. . .
Архитектура биовида Стива в Майнкрафте: Зачем бонобо кубический каннибализм
anaschu 30.08.2026
Кубический Вагинокапитализм в Minecraft: Математический инвариант ОДУ и рок Стивов-бонобо Главная задача разработанной «Модели Всего» — наглядно продемонстрировать наличие системной «судьбы». . .
Оттачиваю умение писать js программы.
russiannick 30.08.2026
Проектом выходного дня стало написание Книги шифров Виженера. Итогом стала версия 200, синий туман. Синий туман назван так, потому что замораживает текст под собой. Нажатие синих кнопок управляют. . .
КиберФорум - форум программистов, компьютерный форум, программирование
Powered by vBulletin
Copyright ©2000 - 2026, CyberForum.ru