Конечно, это стандартное упражнение по кодированию.
Прежде всего, пусть любая биективная вычислимая функция, называемая парной функцией. Стандартный выборp:N2→N
p(n,m)=(n+m)(n+m+1)2+n
Можно доказать, что это биекция, поэтому при любом натуральном мы можем вычислить n , m так , чтобы p ( n , m ) = k .kn,mp(n,m)=k
Чтобы перечислить лямбда-термины, исправьте любое перечисление для имен переменных: .x0,x1,x2,…
Затем для каждого натурального числа выведите l a m b d a ( i ) , рекурсивно определенное следующим образом:ilambda(i)
- если четный, пусть j = i / 2 и возвращает переменную x jij=i/2xj
- если нечетный, пусть j = ( i - 1 ) / 2яj = ( i - 1 ) / 2
- если четно, пусть k = j / 2 и найдем n , m такое, что p ( n , m ) = k ; вычислить N = l a m b d a ( n ) , M = l a m b d a ( m ) ; обратная заявка ( N M )Jk = j / 2н , мp ( n , m ) = kN= l a m b dа ( н ) , М= l a m b dа ( м )( NM)
- если нечетно, пусть k = ( j - 1 ) / 2 и найдем n , m такое, что p ( n , m ) = k ; вычислить M = l a m b d a ( m ) ; возвратная абстракция ( λ x n . M )Jk = ( j - 1 ) / 2н , мp ( n , m ) = kM= l a m b dа ( м )( λ xN, M )
Эта программа обоснована следующей «алгебраической» биекцией, включающей множество всех лямбда-членов :Λ
Λ ≃ N + ( Λ2+ N × Λ )
который читается как «лямбда-термины, синтаксически - это непересекающееся объединение 1) переменных (представленных как натуральные), 2) приложений (составленных из двух лямбда-терминов) и 3) абстракции (парная переменная / натуральная + лямбда-член )».
Учитывая это, мы рекурсивно применяем вычислимые биекции ( p ) и N + N ≃ N (стандартная четная / нечетная) для получения алгоритма, описанного выше.N2≃ NпN + N ≃ N
Эта процедура является общей и будет работать практически на любом языке, сгенерированном с помощью контекстно-свободной грамматики, которая обеспечит изоморфизм, аналогичный приведенному выше.