Конечно, это стандартное упражнение по кодированию.
Прежде всего, пусть любая биективная вычислимая функция, называемая парной функцией. Стандартный выбор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
Эта процедура является общей и будет работать практически на любом языке, сгенерированном с помощью контекстно-свободной грамматики, которая обеспечит изоморфизм, аналогичный приведенному выше.
if n%2==0 ...
Да. Возьмите что-то, что перечисляет все возможные строки ASCII. Для каждого вывода проверьте, является ли он допустимым синтаксисом лямбда-исчисления, который определяет функцию; если нет, пропустите это. (Эту проверку можно сделать.) Перечисляет все функции лямбда-исчисления.
источник
Как уже упоминалось, это просто перечисление терминов из языка без контекста, так что это определенно выполнимо. Но за этим стоит более интересная математика, уходящая в область анлитической комбинаторики.
В статье Подсчет и генерация членов в двоичном лямбда-исчислении содержится обработка проблемы перечисления и многое другое. Чтобы упростить задачу , они используют нечто, называемое двоичным лямбда-каллусом , которое представляет собой просто кодировку лямбда-терминов с использованием индексов Де Брюина , поэтому вам не нужно называть переменные.
Эта статья также содержит конкретный код на Haskell, реализующий алгоритм их генерации. Это определенно эффективно возможно.
Я случайно написал реализацию их подхода в Юлии.
источник
Конечно. Мы можем напрямую генерировать их в соответствии с определением лямбда-терминов.
В Haskell мы сначала определяем тип данных,
а затем с использованием ярмарки (эр)
join
,мы просто перечисляем их, например,
Посмотрите, знаменитый членΩ = ( λ x . X x ) ( λ x . X x ) находится не так далеко от вершины!
fjoin
эквивалентно Omega монады «sdiagonal
.источник
В Интернете я наткнулся на один инструмент, который может генерировать образцы строк из регулярного выражения: https://www.browserling.com/tools/text-from-regex . Вы можете сгенерировать много примеров лямбда-терминов, введя что-то вроде этого:
Конечно, чтобы получить термины с произвольными уровнями вложенности, вам нужно будет использовать контекстно-свободную грамматику, которая является более описательным инструментом для определения языка, чем регулярное выражение. Я не сталкивался с существующим инструментом для генерирования типовых предложений на основе определения грамматики без контекста, но нет причин, по которым его нельзя было бы построить.
источник