Представление натуральных чисел в виде функций высшего порядка
В математике кодировка Чёрча — это способ представления данных и операторов в лямбда-исчислении . Числа Чёрча — это представление натуральных чисел с использованием лямбда-нотации. Метод назван в честь Алонзо Чёрча , который впервые закодировал данные в лямбда-исчислении таким образом.
Термины, которые обычно считаются примитивными в других нотациях (такие как целые числа, булевы значения, пары, списки и помеченные объединения), отображаются в функции более высокого порядка в кодировке Чёрча. Тезис Чёрча–Тьюринга утверждает, что любой вычислимый оператор (и его операнды) могут быть представлены в кодировке Чёрча. [ dubious – discussion ] В нетипизированном лямбда-исчислении единственным примитивным типом данных является функция.
Использовать
Простая реализация кодировки Чёрча замедляет некоторые операции доступа от до , где — размер структуры данных, что делает кодировку Чёрча непрактичной. [1] Исследования показали, что эту проблему можно решить с помощью целевых оптимизаций, но большинство функциональных языков программирования вместо этого расширяют свои промежуточные представления, чтобы они содержали алгебраические типы данных . [2] Тем не менее кодировка Чёрча часто используется в теоретических рассуждениях, поскольку она является естественным представлением для частичной оценки и доказательства теорем. [1] Операции можно типизировать с использованием типов более высокого ранга , [3] и примитивная рекурсия легко доступна. [1] Предположение, что функции являются единственными примитивными типами данных, упрощает многие доказательства.
Кодирование Чёрча является полным, но только репрезентативным. Для перевода представления в общие типы данных для отображения людям необходимы дополнительные функции. В общем случае невозможно решить, являются ли две функции экстенсионально равными из-за неразрешимости эквивалентности из теоремы Чёрча . Перевод может каким-то образом применить функцию для извлечения значения, которое она представляет, или найти ее значение как буквальный лямбда-терм. Лямбда-исчисление обычно интерпретируется как использующее интенсиональное равенство . Существуют потенциальные проблемы с интерпретацией результатов из-за разницы между интенсиональным и экстенсиональным определением равенства.
Церковные цифры
Цифры Чёрча являются представлениями натуральных чисел в кодировке Чёрча. Функция высшего порядка , представляющая натуральное число n, является функцией, которая отображает любую функцию в её n -кратную композицию . Проще говоря, «значение» цифры эквивалентно количеству раз, которое функция инкапсулирует свой аргумент.
Все числа Чёрча являются функциями, принимающими два параметра. Числа Чёрча 0 , 1 , 2 , ..., определяются следующим образом в лямбда-исчислении .
Начиная с 0, не применяя функцию вообще, продолжаем с 1, применяя функцию один раз, 2, применяя функцию дважды, 3, применяя функцию трижды и т. д .:
Числовое значение 3 в трактовке Чёрча представляет собой действие применения любой заданной функции три раза к значению. Предоставленная функция сначала применяется к предоставленному параметру, а затем последовательно к своему собственному результату. Конечным результатом не является число 3 (если только предоставленный параметр не равен 0, а функция не является функцией- последователем ). Сама функция, а не ее конечный результат, является числительным значением 3 в трактовке Чёрча . Числительное значение 3 в трактовке Чёрча просто означает сделать что-либо три раза. Это наглядная демонстрация того, что подразумевается под «тремя разами».
Расчет с помощью церковных цифр
Арифметические операции над числами могут быть представлены функциями над числами Чёрча. Эти функции могут быть определены в лямбда-исчислении или реализованы в большинстве функциональных языков программирования (см. преобразование лямбда-выражений в функции ).
Функция сложения использует тождество .
Функция преемника β - эквивалентна .
Функция умножения использует тождество .
Функция возведения в степень задается определением чисел Чёрча, . В определении подставим, чтобы получить и,
что дает лямбда-выражение,
Функцию понять сложнее.
Число Чёрча применяет функцию n раз. Функция-предшественник должна возвращать функцию, которая применяет свой параметр n - 1 раз. Это достигается путем построения контейнера вокруг f и x , который инициализируется таким образом, что пропускает применение функции в первый раз. См. previous для более подробного объяснения.
Функцию вычитания можно записать на основе предшествующей функции.
Таблица функций над церковными числами
Примечания :
- ^ Эта формула является определением числа Чёрча n с .
- ^ ab В церковной кодировке,
Вывод функции-предшественника
Функция-предшественник, используемая в кодировке Чёрча, следующая:
- .
Нам нужен способ применения функции на 1 раз меньше для построения предшественника. Число n применяет функцию f n раз к x . Функция-предшественник должна использовать число n для применения функции n -1 раз.
Перед реализацией функции-предшественника, вот схема, которая оборачивает значение в функцию-контейнер. Мы определим новые функции для использования вместо f и x , называемые inc и init . Функция-контейнер называется value . В левой части таблицы показано число n , примененное к inc и init .
Общее правило повторения таково:
Если также имеется функция для извлечения значения из контейнера (называемая extract ),
Тогда extract может быть использован для определения функции samenum следующим образом:
Функция samenum сама по себе бесполезна. Однако, поскольку inc делегирует вызов f своему аргументу-контейнеру, мы можем организовать так, чтобы при первом применении inc получал специальный контейнер, который игнорирует свой аргумент, позволяя пропустить первое применение f . Назовем этот новый начальный контейнер const . Правая часть приведенной выше таблицы показывает расширения n inc const . Затем, заменив init на const в выражении для той же функции, мы получим функцию-предшественника,
Как поясняется ниже, функции inc , init , const , value и extract могут быть определены следующим образом:
Что дает лямбда-выражение для pred как,
Другой способ определения pred
Pred также можно определить с помощью пар:
Это более простое определение, но приводит к более сложному выражению для pred. Расширение для :
Разделение
Деление натуральных чисел можно реализовать с помощью, [4]
Вычисление требует много бета-сокращений. Если только вы не делаете сокращение вручную, это не имеет большого значения, но предпочтительнее не делать это вычисление дважды. Простейшим предикатом для проверки чисел является IsZero , поэтому рассмотрим условие.
Но это условие эквивалентно , а не . Если использовать это выражение, то математическое определение деления, данное выше, переводится в функцию над числами Чёрча как,
Как и ожидалось, это определение имеет один вызов . Однако результатом является то, что эта формула дает значение .
Эту проблему можно исправить, добавив 1 к n перед вызовом деления . Определение деления тогда следующее:
divide1 — рекурсивное определение. Для реализации рекурсии можно использовать комбинатор Y. Создайте новую функцию с именем div by;
- С левой стороны
- С правой стороны
получить,
Затем,
где,
Дает,
Или как текст, используя \ вместо λ ,
делим = (\n.((\f.(\xx x) (\xf (xx))) (\c.\n.\m.\f.\x.(\d.(\nn (\x .(\a.\bb)) (\a.\ba)) d ((\f.\xx) fx) (f (cdmfx))) ((\m.\nn (\n.\f.\ xn (\g.\hh (gf)) (\ux) (\uu)) m) nm))) ((\n.\f.\x. f (nfx)) n))
Например, 9/3 представлено как
делим (\f.\xf (f (f (f (f (f (f (f (f (fx))))))))) (\f.\xf (f (fx)))
Используя калькулятор лямбда-исчисления, приведенное выше выражение сокращается до 3, используя обычный порядок.
\ф.\хф (ф (ф (х)))
Подписанные числа
Одним из простых подходов к расширению чисел Чёрча до знаковых чисел является использование пары Чёрча, содержащей числа Чёрча, представляющие положительное и отрицательное значение. [5] Целое значение представляет собой разницу между двумя числами Чёрча.
Натуральное число преобразуется в число со знаком с помощью,
Отрицание выполняется путем перестановки значений.
Целочисленное значение представляется более естественно, если одно из пары равно нулю. Функция OneZero достигает этого условия,
Рекурсию можно реализовать с помощью комбинатора Y,
Плюс и минус
Сложение определяется математически по паре следующим образом:
Последнее выражение переводится в лямбда-исчисление как:
Аналогично определяется вычитание,
давая,
Умножение и деление
Умножение может быть определено как,
Последнее выражение переводится в лямбда-исчисление как:
Аналогичное определение дано здесь для деления, за исключением того, что в этом определении одно значение в каждой паре должно быть равно нулю (см. OneZero выше). Функция divZ позволяет нам игнорировать значение, имеющее нулевой компонент.
Затем divZ используется в следующей формуле, которая аналогична формуле умножения, но с заменой mult на divZ .
Рациональные и действительные числа
Рациональные и вычислимые действительные числа также могут быть закодированы в лямбда-исчислении. Рациональные числа могут быть закодированы как пара знаковых чисел. Вычислимые действительные числа могут быть закодированы с помощью ограничивающего процесса, который гарантирует, что разница с действительным значением отличается на число, которое может быть сделано настолько малым, насколько нам нужно. [6] [7] Приведенные ссылки описывают программное обеспечение, которое теоретически может быть переведено в лямбда-исчисление. После определения действительных чисел комплексные числа естественным образом кодируются как пара действительных чисел.
Описанные выше типы данных и функции демонстрируют, что любой тип данных или вычисление может быть закодировано в лямбда-исчислении. Это тезис Чёрча-Тьюринга .
Перевод с другими представлениями
Большинство реальных языков поддерживают машинно-родные целые числа; функции church и unchurch преобразуют неотрицательные целые числа в соответствующие им числительные Church. Функции приведены здесь на Haskell , где \
соответствует λ лямбда-исчисления. Реализации на других языках аналогичны.
тип Церковь а = ( а -> а ) -> а -> а церковь :: Целое число -> Церковь Целое число церковь 0 = \ f -> \ x -> x церковь n = \ f -> \ x -> f ( церковь ( n - 1 ) f x ) unchurch :: Церковь Целое число -> Целое число unchurch cn = cn ( + 1 ) 0
Церковные булевы операторы
Булевы значения Church — это кодировка Church для булевых значений true и false. Некоторые языки программирования используют их в качестве модели реализации для булевой арифметики; примерами являются Smalltalk и Pico .
Булева логика может рассматриваться как выбор. Кодировка Чёрча истинности и ложности является функцией двух параметров:
- true выбирает первый параметр.
- false выбирает второй параметр.
Эти два определения известны как булевы операторы Чёрча:
Это определение позволяет предикатам (т.е. функциям, возвращающим логические значения ) напрямую действовать как if-предложения. Функция, возвращающая логическое значение, которое затем применяется к двум параметрам, возвращает либо первый, либо второй параметр:
оценивается как then-clause, если predicate-x оценивается как true , и как else-clause, если predicate-x оценивается как false .
Поскольку true и false выбирают первый или второй параметр, их можно объединить для предоставления логических операторов. Обратите внимание, что существует несколько возможных реализаций not .
Вот несколько примеров:
Предикаты
Предикат — это функция, которая возвращает логическое значение. Наиболее фундаментальным предикатом является , который возвращает , если его аргументом является число Чёрча , и если его аргументом является любое другое число Чёрча:
Следующий предикат проверяет, является ли первый аргумент меньшим или равным второму:
- ,
Из-за идентичности,
Тест на равенство может быть реализован следующим образом:
Церковные пары
Пары Чёрча — это кодировка Чёрча типа пары (двухкортежного типа). Пара представлена как функция, которая принимает аргумент функции. При указании аргумента она применит аргумент к двум компонентам пары. Определение в лямбда-исчислении :
Например,
Список кодировок
Список ( неизменяемый ) создается из узлов списка. Основные операции над списком:
Ниже мы приводим четыре различных представления списков:
- Постройте каждый узел списка из двух пар (чтобы допустить наличие пустых списков).
- Постройте каждый узел списка из одной пары.
- Представьте список с помощью функции правой свёртки .
- Представьте список, используя кодировку Скотта, которая принимает случаи выражения соответствия в качестве аргументов.
Две пары как узел списка
Непустой список может быть реализован парой Чёрча;
- Первый содержит голову.
- Во втором случае имеется хвост.
Однако это не дает представления пустого списка, поскольку нет указателя "null". Для представления null пара может быть обернута в другую пару, что даст три значения:
- Сначала — нулевой указатель (пустой список).
- Во-вторых, во-первых, содержится голова.
- Во-вторых. Во-вторых, содержится хвост.
Используя эту идею, основные операции со списками можно определить следующим образом: [8]
В нулевом узле второй никогда не доступен, при условии, что заголовок и хвост применяются только к непустым спискам.
Одна пара как узел списка
В качестве альтернативы, определите [9]
где последнее определение является частным случаем общего
Представьте список, используяправая складка
В качестве альтернативы кодированию с использованием пар Чёрча список можно закодировать, отождествив его с его правой функцией свёртки . Например, список из трёх элементов x, y и z можно закодировать функцией более высокого порядка, которая при применении к комбинатору c и значению n возвращает cx (cy (czn)).
Этому списковому представлению можно присвоить тип в Системе F.
Представьте список с помощью кодировки Скотта
Альтернативным представлением является кодирование Скотта, которое использует идею продолжений и может привести к более простому коду. [10] (см. также кодирование Могенсена–Скотта ).
В этом подходе мы используем тот факт, что списки можно наблюдать с помощью выражения сопоставления с образцом. Например, используя нотацию Scala , если list
обозначает значение типа List
с пустым списком Nil
и конструктором, Cons(h, t)
мы можем проверить список и вычислить, nilCode
если список пуст и consCode(h, t)
когда список не пуст:
список совпадений { case Nil => nilCode case Cons ( h , t ) => consCode ( h , t ) }
Задается list
тем, как он действует на nilCode
и consCode
. Поэтому мы определяем список как функцию, которая принимает такие nilCode
и consCode
в качестве аргументов, так что вместо приведенного выше сопоставления с образцом мы можем просто написать:
Обозначим через n
параметр, соответствующий nilCode
, а через c
параметр, соответствующий consCode
. Пустой список — это тот, который возвращает аргумент nil:
Непустой список с головой h
и хвостом t
задается формулой
В более общем смысле, алгебраический тип данных с альтернативами становится функцией с параметрами. Когда конструктор th имеет аргументы, соответствующий параметр кодировки также принимает аргументы.
Кодирование Скотта может быть выполнено в нетипизированном лямбда-исчислении, тогда как его использование с типами требует системы типов с рекурсией и полиморфизмом типов. Список с типом элемента E в этом представлении, который используется для вычисления значений типа C, будет иметь следующее рекурсивное определение типа, где '=>' обозначает тип функции:
тип List = C => // аргумент nil ( E => List => C ) => // аргумент cons C // результат сопоставления с образцом
Список, который может быть использован для вычисления произвольных типов, будет иметь тип, который квантифицирует по C
. Список generic [ необходимо пояснение ] в E
также будет принимать E
в качестве аргумента типа.
Смотрите также
Ссылки
- ^ abc Trancón y Widemann, Baltasar; Parnas, David Lorge (2008). "Tabular Expressions and Total Functional Programming". В Olaf Chitil; Zoltán Horváth; Viktória Zsók (ред.). Implementation and Application of Functional Languages. 19-й международный семинар, IFL 2007, Фрайбург, Германия, 27–29 сентября 2007 г. Пересмотренные избранные статьи. Lecture Notes in Computer Science. Том 5083. С. 228–229. doi :10.1007/978-3-540-85373-2_13. ISBN 978-3-540-85372-5.
- ^ Янсен, Ян Мартин; Купман, Питер ВМ; Пласмейер, Маринус Дж. (2006). «Эффективная интерпретация путем преобразования типов данных и шаблонов в функции». В Нильссон, Хенрик (ред.). Тенденции в функциональном программировании. Том 7. Бристоль: Intellect. стр. 73–90. CiteSeerX 10.1.1.73.9841 . ISBN 978-1-84150-188-8.
- ^ «Предшественник и списки не могут быть представлены в простом типизированном лямбда-исчислении». Лямбда-исчисление и лямбда-калькуляторы . okmij.org.
- ^ Эллисон, Ллойд. «Лямбда-исчисление целых чисел».
- ^ Бауэр, Андрей. «Ответ Андрея на вопрос: «Представление отрицательных и комплексных чисел с помощью лямбда-исчисления»».
- ^ "Точная вещественная арифметика". Haskell . Архивировано из оригинала 2015-03-26.
- ^ Бауэр, Андрей (26 сентября 2022 г.). "Программное обеспечение для вычисления действительных чисел". GitHub .
- ^ Пирс, Бенджамин С. (2002). Типы и языки программирования . MIT Press . стр. 500. ISBN 978-0-262-16209-8.
- ^ Тромп, Джон (2007). "14. Двоичное лямбда-исчисление и комбинаторная логика". В Calude, Cristian S (ред.). Случайность и сложность, от Лейбница до Хайтина . World Scientific. стр. 237–262. ISBN 978-981-4474-39-9.
В формате PDF: Тромп, Джон (14 мая 2014 г.). «Двоичное лямбда-исчисление и комбинаторная логика» (PDF) . Получено 24.11.2017 . - ^ Янсен, Ян Мартин (2013). «Программирование в λ-исчислении: от Чёрча до Скотта и обратно». В Ахтен, Питер; Купман, Питер ВМ (ред.). Красота функционального кода — эссе, посвящённые Ринусу Пласмейеру по случаю его 61-го дня рождения . Конспект лекций по информатике. Том 8106. Springer. С. 168–180. doi :10.1007/978-3-642-40355-2_12.
- Stump, A. (2009). «Прямо рефлексивное метапрограммирование» (PDF) . High-Order Symb Comput . 22 (2): 115–144. CiteSeerX 10.1.1.489.5018 . doi :10.1007/s10990-007-9022-0. S2CID 16124152.
- Картрайт, Роберт. "Объяснение церковных цифр и булевых значений" (PDF) . Comp 311 — Обзор 2 . Университет Райса .
- Кемп, Колин (2007). "§2.4.1 Church Naturals, §2.4.2 Church Booleans, Гл. 5 Методы вывода для TFP". Теоретические основы практического "полностью функционального программирования"(PhD). Факультет информационных технологий и электротехники, Университет Квинсленда. С. 14–17, 93–145. CiteSeerX 10.1.1.149.3505 . Все о кодировках Чёрча и других подобных кодировках, включая способы их получения и операции над ними, из первых принципов
- Некоторые интерактивные примеры церковных цифр
- Учебное пособие по лямбда-исчислению: Булева алгебра