Кодирование Чёрча

Материал из testwiki
Перейти к навигации Перейти к поиску

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

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

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

Числа Чёрча

Представления натуральных чисел в кодировке Чёрча называются числами Чёрча. Число Чёрча, соответствующее натуральному числу n, определяется как функция от двух параметров f и x, применяющая f к x n раз — другими словами, число Чёрча отображает функцию f в её n-кратную композицию:

fn=fffn раз.

0 f x значит «не применять функцию f к x вообще», 1 f x значит «применять функцию 1 раз» и т. д.:

Число Определение нумерала Лямбда-выражение
0 0 f x=x 0=λf.λx.x
1 1 f x=f x 1=λf.λx.f x
2 2 f x=f (f x) 2=λf.λx.f (f x)
3 3 f x=f (f (f x)) 3=λf.λx.f (f (f x))
n n f x=fn x n=λf.λx.fn x

Вычисления над числами Чёрча

Арифметические операции над числами можно представить в лямбда-исчислении, как функции над числами Чёрча.

Шаблон:Дополнить раздел

Булеаны Чёрча

Представление булевых значений (Шаблон:Lang-en), то есть «истина» (Шаблон:Lang-en) и «ложь» (Шаблон:Lang-en) в кодировке Чёрча называется булеанами Чёрча. Некоторые языки программирования, такие как Smalltalk и Pico, используют их в качестве модели реализации для булевой арифметики.

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

  • true из двух аргументов выбирает первый ― trueλa.λb.a.
  • false из двух аргументов выбирает второй ― falseλa.λb.b.

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

xпредикат ветвьто ветвьиначе

вычисляется как ветвь-то, если х-предикат выдаёт истинное значение, и как ветвь-иначе, если х-предикат выдаёт ложное.

Над true и false могут быть реализованы стандартные логические операторы (AND, OR, NOT, XOR, if).

and=λp.λq.p q por=λp.λq.p p qnot=λp.pfalsetrue=λp.p (λa.λb.b) (λa.λb.a)=λp.λa.λb.p b axor=λa.λb.a (not b) bif=λp.λa.λb.p a b

Несколько примеров:

andtruefalse=(λp.λq.p q p)truefalse=truefalsetrue=(λa.λb.a)falsetrue=falseortruefalse=(λp.λq.p p q)truefalse=truetruefalse=(λa.λb.a)truefalse=truenottrue=(λp.pfalsetrue)true=truefalsetrue=(λa.λb.a)falsetrue=false

Предикаты

Предикатами называются функции, возвращающие логическое значение.

Одним из базовых предикатов является IsZero, который возвращает true, если его аргумент является числом Чёрча 0, и false, если его аргумент является любым другим:

IsZero=λn.n (λx.false) true

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

LEQ=λm.λn.IsZero (minus m n),

Из тождества x=y(xyyx) получается предикат проверки на равeнство EQ:

EQ=λm.λn.and (LEQ m n) (LEQ n m)

Пары Чёрча

Шаблон:Seealso

Представление в кодировке Чёрча пар, то есть наборов из двух элементов, называется парами Чёрча. Пара представляется как функция, которая применяет свой единственный аргумент f к обоим элементам пары x и y, получая в результате f x y.

Определение в лямбда-исчислении функции pair, возвращающей пару из двух элементов, и функций first и second, возвращающих соответственно первый и второй элемент пары:

pairλx.λy.λz.z x yfirstλp.p (λx.λy.x)secondλp.p (λx.λy.y)

Пример:

first (pair a b)=(λp.p (λx.λy.x)) ((λx.λy.λz.z x y) a b)=(λp.p (λx.λy.x)) (λz.z a b)=(λz.z a b) (λx.λy.x)=(λx.λy.x) a b=a

Списки Чёрча

(Неизменяемый) список состоит из нескольких элементов. Ниже приводятся основные операции, которые должны быть реализованы для списка:

Функция Описание
nil Возвращает пустой список.
isnil Проверяет, является ли список пустым.
cons Вставляет переданное значение в начало (возможно пустого) списка.
head Возвращает первый элемент списка.
tail Возвращает весь список, кроме первого элемента.

С их помощью, например, можно реализовать функцию вычисления длины списка length:

length=λl.if (isnill) 0 (inclengthtaill)

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

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

Представление в виде двух пар

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

  • Первый элемент содержит первый элемент списка.
  • Второй содержит оставшиеся элементы («хвост» списка).

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

  • Первый элемент — является ли список пустым.
  • Второй элемент ― пара из первого элемента списка и хвоста списка.

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

Функция Описание
nilpair true true Первый элемент пары true означает пустоту списка.
isnilfirst Возвращает первый элемент пары, который и означает, является ли список пустым.
consλh.λt.pairfalse (pairh t) Создаём новый непустой список из первого элемента (головы списка) h и хвоста t.
headλz.first (secondz) Первый элемент пары во втором элементе — голова списка.
tailλz.second (secondz) Второй элемент пары во втором элементе — хвост списка.

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

Представление в виде одной пары

В качестве альтернативы, списки можно определить следующим образом (false соответствует пустому списку, непустые задаются парой головы и хвоста):[2]

conspairheadfirsttailsecondnilfalseisnilλl.l(λh.λt.λd.false)true

где последнее определение — пример более общей функции:

process-listλl.l(λh.λt.λd. функция от головы и хвоста) случай пустого списка

Представление списка через функцию свёртки справа

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

nilλc.λn.nisnilλl.l (λh.λt.false) trueconsλh.λt.λc.λn.c h (t c n)headλl.l (λh.λt.h) falsetailλl.λc.λn.l (λh.λt.λg.g h (t c)) (λt.n) (λh.λt.t)

Представление списка с использованием кодирования Скотта

Ещё одним альтернативным представлением является представление списков через кодирование Скотта, которое использует идею продолжения и может привести к упрощению кода[3]. (см. также Шаблон:Iw). В этом подходе используется факт, что списки можно обрабатывать путём сопоставления с образцом.

См. также

Примечания

Шаблон:Примечания

Литература