Церковная кодировка

Из Википедии, бесплатной энциклопедии

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

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

Используйте [ править ]

Простая реализация кодирования Чёрча замедляет некоторые операции доступа из к , где — это размер структуры данных, что делает кодирование Чёрча непрактичным. [1] Исследования показали, что эту проблему можно решить путем целенаправленной оптимизации, но большинство функциональных языков программирования вместо этого расширяют свои промежуточные представления, чтобы они содержали алгебраические типы данных . [2] Тем не менее, кодирование Чёрча часто используется в теоретических аргументах, поскольку оно является естественным представлением для частичной оценки и доказательства теорем. [1] Операции можно типизировать с использованием типов более высокого ранга . [3] и примитивная рекурсия легко доступна. [1] Предположение о том, что функции являются единственными примитивными типами данных, упрощает многие доказательства.

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

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

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

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

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

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

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

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

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

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

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

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

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

The функцию сложнее понять.

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

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

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

Функция Алгебра Личность Определение функции Лямбда-выражения
Преемник ...
Добавление
Умножение
Возведение в степень [а]
Предшественник [б]

Вычитание [б] ( Монус ) ...

информация Примечание:

  1. ^ Эта формула представляет собой определение числа Чёрча n с .
  2. ^ Перейти обратно: а б В кодировке Чёрча

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

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

.

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

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

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

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

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

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

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

Что дает лямбда-выражение для pred as:

Контейнер значений [ править ]

Контейнер значений применяет функцию к своему значению. Это определяется,

так,

Инк [ править ]

Функция inc должна принимать значение, содержащее v , и возвращать новое значение, содержащее fv .

Пусть g будет контейнером значений,

затем,

так,

Извлечь [ править ]

Значение можно извлечь, применив функцию идентификации:

Используя Я ,

так,

Константа [ править ]

Для реализации pred функция init заменяется константой , которая не применяет f . Нам нужна константа , чтобы удовлетворить,

Что будет удовлетворено, если

Или как лямбда-выражение,

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

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

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

Дивизия [ править ]

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

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

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

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

Эту проблему можно исправить, добавив 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 в обычном порядке.

\f.\xf (f (f (x)))
 

Числа со знаком [ править ]

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

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

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

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

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

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

Сложение определяется математически для пары следующим образом:

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

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

предоставление,

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

Умножение может быть определено как:

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

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

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

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

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

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

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

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

тип   Церковь   a   =   (  a   ->   a  )   ->   a   ->   церковь 

 \   ::   Целое число   ->   Церковь   Целое число 
 =   церковь 0   f   -  >   \   x  -   >   x 
 церковь   n   =   \  f   ->   \  x   ->   f   (  церковь   (  n  -  1  )   f   x  ) 

 unchurch   ::   Church   Integer   >   Inchurch 
 -   cn   =   cn   (  +   1  )   0 

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

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

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

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

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

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

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

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

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

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

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

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

,

Из-за идентичности,

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

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

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

Например,

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

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

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

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

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

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

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

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

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

  • Сначала — нулевой указатель (пустой список).
  • Второй. Первый содержит голову.
  • Second.Second содержит хвост.

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

Выражение Описание
Первый элемент пары имеет значение true, что означает, что список имеет значение NULL.
Получите нулевой индикатор (или пустой список).
Создайте узел списка, который не равен нулю, и присвойте ему заголовок h и конец t .
второе.первое — голова.
секунда.секунда — это хвост.

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

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

В качестве альтернативы определите [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  ) 
 } 

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

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

Непустой список с заголовком h и хвост t дан кем-то

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

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

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

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

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

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

  1. ^ Перейти обратно: а б с Транкон и Видеманн, Бальтасар; Парнас, Дэвид Лорхе (2008). «Табличные выражения и полное функциональное программирование». У Олафа Читиля; Золтан Хорват; Виктория Жок (ред.). Реализация и применение функциональных языков . 19-й международный семинар IFL 2007, Фрайбург, Германия, 27–29 сентября 2007 г. Пересмотренные избранные статьи. Конспекты лекций по информатике. Том. 5083. стр. 228–229. дои : 10.1007/978-3-540-85373-2_13 . ISBN  978-3-540-85372-5 .
  2. ^ Янсен, Ян Мартин; Купман, Питер ВМ; Пласмейер, Маринус Дж. (2006). «Эффективная интерпретация путем преобразования типов данных и шаблонов в функции». Нильссон, Хенрик (ред.). Тенденции функционального программирования. Том 7 . Бристоль: Интеллект. стр. 73–90. CiteSeerX   10.1.1.73.9841 . ISBN  978-1-84150-188-8 .
  3. ^ «Предшественник и списки не могут быть представлены в просто типизированном лямбда-исчислении» . Лямбда-исчисление и лямбда-калькуляторы . okmij.org.
  4. ^ Эллисон, Ллойд. «Целые числа лямбда-исчисления» .
  5. ^ Бауэр, Андрей. "Ответ Андрея на вопрос: "Представление отрицательных и комплексных чисел с помощью лямбда-исчисления" " .
  6. ^ «Точная действительная арифметика» . Хаскелл . Архивировано из оригинала 26 марта 2015 г.
  7. ^ Бауэр, Андрей (26 сентября 2022 г.). «Программное обеспечение для вычислений с вещественными числами» . Гитхаб .
  8. ^ Пирс, Бенджамин К. (2002). Типы и языки программирования . МТИ Пресс . п. 500. ИСБН  978-0-262-16209-8 .
  9. ^ Тромп, Джон (2007). «14. Бинарное лямбда-исчисление и комбинаторная логика» . В Калуде, Кристиан С. (ред.). Случайность и сложность: от Лейбница до Хайтина . Всемирная научная. стр. 237–262. ISBN  978-981-4474-39-9 .
    В формате PDF: Тромп, Джон (14 мая 2014 г.). «Двоичное лямбда-исчисление и комбинаторная логика» (PDF) . Проверено 24 ноября 2017 г.
  10. ^ Янсен, Ян Мартин (2013). «Программирование в λ-исчислении: от Черча до Скотта и обратно». В Ахтене, Питер; Купман, Питер В.М. (ред.). Красота функционального кода — очерки, посвящённые Ринусу Пласмейеру по случаю его 61-летия . Конспекты лекций по информатике. Том. 8106. Спрингер. стр. 168–180. дои : 10.1007/978-3-642-40355-2_12 .