Claro, este é um exercício de codificação padrão.
Antes de tudo, deixe qualquer função computável bijetiva, chamada função de emparelhamento. Uma escolha padrão ép:N2→N
p(n,m)=(n+m)(n+m+1)2+n
Pode-se provar que isso é uma bijeção, portanto, dado qualquer natural , podemos calcular n , m de modo que p ( n , m ) = k .kn,mp(n,m)=k
Para enumerar termos lambda, corrija qualquer enumeração para nomes de variáveis: .x0,x1,x2,…
Então, para cada número natural , imprima l a m b d a ( i ) , definido recursivamente da seguinte maneira:ilambda(i)
- se for par, deixe j = i / 2 e retorne a variável x jij=i/2xj
- se é ímpar, seja j = ( i - 1 ) / 2ij=(i−1)/2
- se for par, deixe k = j / 2 e encontre n , m de modo que p ( n , m ) = k ; calcular N = l a m b d a ( n ) , M = l a m b d a ( m ) ; aplicação de devolução ( N M )jk=j/2n,mp(n,m)=kN= l a m b da ( n ) , M= l a m b da ( m )( NM)
- se for ímpar, seja k = ( j - 1 ) / 2 e encontre n , m tal que p ( n , m ) = k ; calcular M = l a m b d a ( m ) ; abstração de retorno ( λ x n . M )jk = ( j - 1 ) / 2n , mp ( n , m ) = kM= l a m b da ( m )( λ xn. M )
Este programa é justificado pela seguinte bijeção "algébrica" envolvendo o conjunto de todos os termos lambda :Λ
Λ ≃ N + ( Λ2+ N × Λ )
que é lido como "os termos lambda, sintaticamente, são a união disjunta de 1) variáveis (representadas como naturais), 2) aplicações (feitas por dois termos lambda) e 3) abstração (um par variável / natural + termo lambda ) ".
Dado isso, aplicamos recursivamente as bijeções computáveis ( p ) e N + N ≃ N (o padrão par / ímpar) para obter o algoritmo acima.N2≃ NpN + N ≃ N
Este procedimento é geral e funcionará em quase qualquer linguagem gerada por meio de uma gramática livre de contexto, que fornecerá um isomorfismo semelhante ao descrito acima.
if n%2==0 ...
Sim. Pegue algo que enumere todas as seqüências ASCII possíveis. Para cada saída, verifique se é uma sintaxe válida de cálculo lambda que define uma função; Caso contrário, pule. (Essa verificação pode ser feita.) Isso enumera todas as funções de cálculo lambda.
fonte
Como foi mencionado, isso é apenas enumerando termos de uma linguagem livre de contexto, tão definitivamente factível. Mas há uma matemática mais interessante por trás disso, entrando no campo da combinatória analítica.
O artigo Contando e gerando termos no cálculo lambda binário contém um tratamento do problema de enumeração e muito mais. Para simplificar, eles usam algo chamado binário lambda calulus , que é apenas uma codificação de termos lambda usando índices De Bruijn , para que você não precise nomear variáveis.
Esse documento também contém código Haskell concreto implementando seu algoritmo de geração. É definitivamente efetivamente possível.
Por acaso, escrevi uma implementação de sua abordagem em Julia.
fonte
Certo. Podemos gerá-los diretamente de acordo com a definição de termos lambda.
Em Haskell, definimos o tipo de dados primeiro,
e depois com o uso de uma feira (er)
join
,apenas as enumeramos, como por exemplo
Olha, o famosoΩ = ( λ x . X x ) ( λ x . X x ) termo está lá não tão longe do topo!
fjoin
é equivalente ao Omega monad 'sdiagonal
.fonte
Encontrei uma ferramenta on-line que pode gerar seqüências de amostra a partir de uma expressão regular: https://www.browserling.com/tools/text-from-regex . Você pode gerar muitos termos lambda de amostra inserindo algo como isto:
Obviamente, para obter termos com níveis arbitrários de aninhamento, você precisará usar uma gramática livre de contexto, que é uma ferramenta mais descritiva para definir um idioma do que uma expressão regular. Eu não encontrei uma ferramenta existente para gerar frases de exemplo de linguagem com base em uma definição gramatical livre de contexto, mas não há razão para que uma não possa ser criada.
fonte