Из Википедии, бесплатной энциклопедии
  (Перенаправлено с церковных цифр )
Перейти к навигации Перейти к поиску

В математике , кодирование Церкви является средством представления данных и операторов в лямбда - исчислении . В позиции Церкви являются представлением натуральных чисел с помощью лямбда - нотации. Метод назван в честь Алонзо Черча , который первым закодировал данные в лямбда-исчислении таким образом.

Термины, которые обычно считаются примитивными в других обозначениях (таких как целые числа, логические значения, пары, списки и помеченные объединения), отображаются в функции высшего порядка в кодировке Чёрча. Тезис Черча-Тьюринга утверждает , что любая вычислимая оператор (и его операнды) могут быть представлены в соответствии с кодированием Church. В нетипизированном лямбда-исчислении единственным примитивным типом данных является функция.

Кодировка Чёрча не предназначена для практической реализации примитивных типов данных. Его использование должно показать, что другие примитивные типы данных не требуются для представления каких-либо вычислений. Полнота репрезентативна. Дополнительные функции необходимы для преобразования представления в общие типы данных для отображения людям. В общем случае невозможно решить, равны ли две функции экстенсивно из-за неразрешимости эквивалентности из теоремы Чёрча . Перевод может каким-либо образом применить функцию для получения значения, которое она представляет, или поиска его значения как буквального лямбда-термина.

Лямбда-исчисление обычно интерпретируется как использование содержательного равенства . Существуют потенциальные проблемы с интерпретацией результатов из-за разницы между интенсиональным и экстенсиональным определениями равенства.

Церковные цифры [ править ]

Цифры Чёрча представляют собой натуральные числа в кодировке Чёрча. Функция высшего порядка , представляющая натуральное число n, является функцией, которая отображает любую функцию в ее n- кратную композицию . Проще говоря, «значение» числа эквивалентно тому, сколько раз функция инкапсулирует свой аргумент.

Все числа Чёрча - это функции, которые принимают два параметра. Цифры Чёрча 0 , 1 , 2 , ... определяются в лямбда-исчислении следующим образом .

Начиная с 0, не применяя функцию вообще, выполните 1, применяя функцию один раз, 2 применяя функцию дважды, 3 применяя функцию три раза и т. Д . :

Цифра 3 Чёрча представляет собой трехкратное применение любой заданной функции к значению. Предоставленная функция сначала применяется к предоставленному параметру, а затем последовательно к собственному результату. Конечным результатом является не цифра 3 (если только предоставленный параметр не равен 0, а функция не является функцией-преемником ). Сама функция, а не ее конечный результат, - это цифра 3 Чёрча . Церковная цифра 3 означает просто сделать что-нибудь трижды. Это явная демонстрация того, что имеется в виду под «трижды».

Расчет с цифрами Чёрча [ править ]

Арифметические операции над числами могут быть представлены функциями над числами Чёрча. Эти функции могут быть определены в лямбда-исчислении или реализованы на большинстве языков функционального программирования (см. Преобразование лямбда-выражений в функции ).

Функция сложения использует идентификатор .

Функция преемника является β-эквивалентна , чтобы .

Функция умножения использует идентичность .

Функция экспоненцирование дается определение Чёрча, . В определении подставьте, чтобы получить и,

что дает лямбда-выражение,

Функция является более трудной для понимания.

Число Чёрча применяет функцию n раз. Функция-предшественник должна возвращать функцию, которая применяет свой параметр n - 1 раз. Это достигается путем создания контейнера вокруг f и x , который инициализируется способом, исключающим применение функции в первый раз. См. Предшественник для более подробного объяснения.

Функцию вычитания можно записать на основе предыдущей функции.

Таблица функций на цифрах Чёрча [ править ]

* Обратите внимание, что в церковной кодировке

Вывод функции-предшественника [ править ]

Функция-предшественник, используемая в кодировке Чёрча:

.

Чтобы построить предшественника, нам нужен способ применения функции на 1 меньше раз. Число n применяет функцию f n раз к x . Функция-предшественник должна использовать цифру n, чтобы применить функцию n -1 раз.

Перед реализацией функции-предшественника приведем схему, которая обертывает значение в функцию-контейнер. Мы определим новые функции, которые будут использоваться вместо f и x , с именами inc и init . Контейнерная функция называется значением . В левой части таблицы показано число n, примененное к inc и init .

Общее правило повторения:

Если есть также функция для извлечения значения из контейнера (называемая экстрактом ),

Затем extract может использоваться для определения той же функции, что и,

Функция samenum по сути бесполезна. Однако, поскольку inc делегирует вызов f своему аргументу-контейнеру, мы можем сделать так, чтобы в первом приложении inc получал специальный контейнер, который игнорирует его аргумент, позволяя пропустить первое применение f . Назовите этот новый начальный контейнер const . В правой части приведенной выше таблицы показаны расширения n inc const . Затем, заменив init на const в выражении той же функции, мы получим функцию-предшественницу,

Как объясняется ниже, функции inc , init , const , value и extract могут быть определены как,

Это дает лямбда-выражение для pred как,

Другой способ определения пред [ править ]

Pred также можно определить с помощью пар:

Это более простое определение, но приводит к более сложному выражению для pred. Расширение для :

Подразделение [ править ]

Деление натуральных чисел может быть реализовано с помощью, [2]

Расчет требует многих сокращений бета-версии. Если сокращение не выполняется вручную, это не имеет большого значения, но желательно не выполнять этот расчет дважды. Самый простой предикат для проверки чисел - IsZero, поэтому учитывайте это условие.

Но это условие эквивалентно , not . Если используется это выражение, то приведенное выше математическое определение деления переводится в функцию на числах Чёрча как,

При желании это определение имеет единственный вызов . Однако в результате эта формула дает значение .

Эту проблему можно исправить, добавив 1 к n перед вызовом div . Тогда определение разделения таково :

div1 - это рекурсивное определение. 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 (fx)))))))) (\ f. \ xf (f (fx)))

Используя калькулятор лямбда-исчисления, приведенное выше выражение сокращается до 3 в обычном порядке.

\ е. \ xf (е (е (х)))

Подписанные числа [ править ]

Один из простых способов расширения цифр Чёрча до чисел со знаком - использовать пару Чёрча, содержащую числа Чёрча, представляющие положительное и отрицательное значение. [3] Целочисленное значение - это разница между двумя цифрами Чёрча.

Натуральное число преобразуется в число со знаком:

Отрицание выполняется заменой значений.

Целочисленное значение более естественно представлено, если одна из пары равна нулю. Функция OneZero выполняет это условие,

Рекурсия может быть реализована с использованием комбинатора Y,

Плюс и минус [ править ]

Сложение определяется математически на паре как

Последнее выражение переводится в лямбда-исчисление как,

Аналогично определяется вычитание,

давая

Умножить и разделить [ править ]

Умножение можно определить следующим образом:

Последнее выражение переводится в лямбда-исчисление как,

Аналогичное определение дается здесь для деления, за исключением того, что в этом определении одно значение в каждой паре должно быть равно нулю (см. OneZero выше). Функция divZ позволяет нам игнорировать значение с нулевым компонентом.

Затем divZ используется в следующей формуле, которая такая же, как для умножения, но с mult, замененным на divZ .

Рациональные и действительные числа [ править ]

Рациональные и вычислимые действительные числа также могут быть закодированы в лямбда-исчислении. Рациональные числа могут быть закодированы как пара чисел со знаком. Вычислимые действительные числа могут быть закодированы с помощью ограничивающего процесса, который гарантирует, что разница от реального значения отличается на число, которое может быть сделано настолько маленьким, насколько нам нужно. [4] [5] Приведенные ссылки описывают программное обеспечение, которое теоретически может быть переведено в лямбда-исчисление. После определения действительных чисел комплексные числа естественным образом кодируются как пара действительных чисел.

Типы данных и функции, описанные выше, демонстрируют, что любой тип данных или вычисления могут быть закодированы в лямбда-исчислении. Это тезис Черча-Тьюринга .

Перевод с другими представлениями [ править ]

Большинство реальных языков поддерживают машинные целые числа; функции церковной и нецерковной преобразуют неотрицательные целые числа и соответствующие им числа Чёрча. Функции приведены здесь в Haskell , где \соответствует λ в лямбда-исчислении. Реализации на других языках аналогичны.

типа  Church  a  =  ( a  ->  a )  ->  a  ->  aцерковь  ::  целое число  ->  церковь  целое число церковь  0  =  \ f  ->  \ x  ->  x церковь  n  =  \ f  ->  \ x  ->  f  ( церковь  ( n - 1 )  f  x )unchurch  ::  Church  Целое  ->  Целое unchurch  cn  =  cn  ( +  1 )  0

Церковные логические значения [ править ]

Булевы значения Чёрча - это Чёрч-кодирование логических значений истина и ложь. Некоторые языки программирования используют их как модель реализации для логической арифметики; примерами являются Smalltalk и Pico .

Булеву логику можно рассматривать как выбор. Кодирование Чёрча истинного и ложного являются функциями двух параметров:

  • true выбирает первый параметр.
  • false выбирает второй параметр.

Эти два определения известны как логические значения Чёрча:

Это определение позволяет предикатам (то есть функциям, возвращающим логические значения ) непосредственно действовать как if-clauses. Функция, возвращающая логическое значение, которое затем применяется к двум параметрам, возвращает либо первый, либо второй параметр:

оценивается как then-clause, если предикат x оценивается как true , и как else-clause, если предикат x оценивается как false .

Поскольку истина и ложь выбирают первый или второй параметр, они могут быть объединены для предоставления логических операторов. Обратите внимание, что существует две версии not , в зависимости от выбранной стратегии оценки .

Некоторые примеры:

Предикаты [ править ]

Предикат является функцией , которая возвращает значение Boolean. Самый фундаментальный предикат - это , который возвращается, если его аргумент - это число Чёрча , а его аргумент - любое другое число Чёрча:

Следующий предикат проверяет, меньше ли первый аргумент второму или равен ему:

,

Из-за личности,

Проверка на равенство может быть реализована как:

Церковные пары [ править ]

Церковные пары - это церковная кодировка парного (двухкортежного) типа. Пара представлена ​​как функция, которая принимает аргумент функции. Получив аргумент, он применит аргумент к двум компонентам пары. Определение в лямбда-исчислении :

Например,

Список кодировок [ править ]

( Неизменяемый ) список состоит из узлов списка. Основные операции в списке:

Ниже мы приводим четыре различных представления списков:

  • Создайте каждый узел списка из двух пар (чтобы учесть пустые списки).
  • Постройте каждый узел списка из одной пары.
  • Представьте список, используя функцию правого сгиба .
  • Представьте список с использованием кодировки Скотта, которая принимает в качестве аргументов случаи выражения соответствия

Две пары как узел списка [ править ]

Непустой список может быть реализован парой Чёрча;

  • Первый содержит голову.
  • Второй содержит хвост.

Однако это не дает представления о пустом списке, потому что нет «нулевого» указателя. Чтобы представить null, пара может быть завернута в другую пару, давая свободные значения,

  • Первый - это нулевой указатель (пустой список).
  • Второй. Первый содержит голову.
  • Во-вторых, во второй - хвост.

Используя эту идею, основные операции со списком можно определить следующим образом: [6]

В нулевом узле второй никогда не обращался, при условии , что голова и хвост применяются только к непустым спискам.

Одна пара как узел списка [ править ]

В качестве альтернативы определите [7]

где последнее определение является частным случаем общего

Представьте список, используя правый сгиб [ править ]

В качестве альтернативы кодированию с использованием пар Чёрча список можно закодировать, отождествив его с функцией правого сгиба . Например, список из трех элементов x, y и z может быть закодирован функцией высшего порядка, которая при применении к комбинатору c и значению n возвращает cx (cy (czn)).

Это представление списка можно задать тип в системе F .

Представьте список, используя кодировку Скотта [ править ]

Альтернативным представлением является кодировка Скотта, которая использует идею продолжений и может привести к упрощению кода. [8] (см. Также кодировку Могенсена – Скотта ).

В этом подходе мы используем тот факт, что списки можно наблюдать с помощью выражения сопоставления с образцом. Например, используя нотацию Scala , if listобозначает значение типа Listс пустым списком Nilи конструктором, Cons(h, t)мы можем проверить список и вычислить, nilCodeесли список пуст и consCode(h, t)когда список не пуст:

список  совпадений  {  case  Nil  =>  nilCode  case  Cons ( h ,  t )  =>  consCode ( h , t ) }

«Список» определяется тем, как он действует с «nilCode» и «consCode». Поэтому мы определяем список как функцию, которая принимает такие 'nilCode' и 'consCode' в качестве аргументов, так что вместо приведенного выше сопоставления с шаблоном мы можем просто написать:

Обозначим через 'n' параметр, соответствующий 'nilCode', а через 'c' - параметр, соответствующий 'consCode'. Пустой список - это тот, который возвращает аргумент nil:

Непустой список с заголовком "h" и хвостом "t" задается следующим образом:

В более общем смысле, алгебраический тип данных с альтернативами становится функцией с параметрами. Когда конструктор th имеет аргументы, соответствующий параметр кодировки также принимает аргументы.

Кодирование Скотта может выполняться в нетипизированном лямбда-исчислении, тогда как для его использования с типами требуется система типов с рекурсией и полиморфизмом типов. Список с типом элемента E в этом представлении, который используется для вычисления значений типа C, будет иметь следующее определение рекурсивного типа, где '=>' обозначает тип функции:

type  List  =  C  =>  // аргумент nil  ( E  =>  List  =>  C )  =>  // аргумент cons  C  // результат сопоставления с образцом

Список, который можно использовать для вычисления произвольных типов, будет иметь тип, который количественно превышает C. Общий список [ требуется пояснение ] в Eтакже будет принимать Eв качестве аргумента типа.

См. Также [ править ]

  • Лямбда-исчисление
  • Система F для чисел Чёрча в типизированном исчислении
  • Кодировка Могенсена – Скотта
  • Определение фон Неймана порядковых чисел - еще один способ кодирования натуральных чисел: как наборы

Примечания [ править ]

  1. ^ Эта формула является определением числа Чёрча n с f -> m, x -> f.
  2. ^ Эллисон, Ллойд. «Целые числа лямбда-исчисления» .
  3. ^ Бауэр, Андрей. «Ответ Андрея на вопрос:« Представление отрицательных и комплексных чисел с помощью лямбда-исчисления » » .
  4. ^ «Точная действительная арифметика» . Haskell .
  5. ^ Бауэр, Андрей. «Программное обеспечение для вычисления вещественных чисел» .
  6. ^ Пирс, Бенджамин С. (2002). Типы и языки программирования . MIT Press . п. 500. ISBN 978-0-262-16209-8.
  7. ^ Тромп, Джон (2007). «14. Двоичное лямбда-исчисление и комбинаторная логика». В Калуде, Кристиан С. (ред.). Случайность и сложность, от Лейбница до Чайтина . World Scientific. С. 237–262. ISBN 978-981-4474-39-9.
    В формате PDF: Тромп, Джон (14 мая 2014 г.). «Двоичное лямбда-исчисление и комбинаторная логика» (PDF) . Проверено 24 ноября 2017 .
  8. ^ Янсен, Ян Мартин (2013). «Программирование в λ-исчислении: от Черча до Скотта и обратно». LNCS . 8106 : 168–180. DOI : 10.1007 / 978-3-642-40355-2_12 .

Ссылки [ править ]

  • Непосредственно отражающее метапрограммирование
  • Церковные числа и логические значения объяснил Роберт Картрайт из Университета Райса
  • Теоретические основы практического «полностью функционального программирования» (главы 2 и 5) Все о церковных и других подобных кодировках, в том числе о том, как их вывести и как с ними работать, из первых принципов
  • Некоторые интерактивные примеры церковных цифр
  • Живое руководство по лямбда-исчислению: логическая алгебра