Lambda Analiz Jeneratörü


10

Bu soruyu başka nereye soracağımı bilmiyorum, umarım burası iyi bir yerdir.

Sadece lambda kalkülüs jeneratörü yapmanın mümkün olup olmadığını bilmek istiyorum; esasen, sonsuz zaman verildiğinde, olası her lambda hesabı işlevini üretecek bir döngü. (bir dize biçiminde olduğu gibi).

Lambda hesabı çok basit olduğundan, gösterimi için sadece birkaç öğeye sahip olduğum için, en basit kombinasyonlardan başlayarak bu gösterim öğelerinin tüm olası kombinasyonlarını üretmenin ve böylece mümkün olan her lambda'yı üretmenin mümkün olabileceğini düşündüm. kalkülüs işlevi.

Tabii ki, lambda hesabı hakkında neredeyse hiçbir şey bilmiyorum, bu yüzden gerçekten mümkün olup olmadığı hakkında hiçbir fikrim yok.

Bu mu? Öyleyse, öngördüğüm gibi oldukça basit mi, yoksa teknik olarak mümkün mü, ancak etkili bir şekilde imkansız olduğu kadar zor mu?

PS. Beta-indirgenmiş fonksiyonlardan bahsetmiyorum, sadece her lambda kalkülüs fonksiyonunun her geçerli göstergesinden bahsediyorum.

Yanıtlar:


19

Elbette, bu standart bir kodlama alıştırmasıdır.

Her şeyden önce, p:N2N , eşleştirme fonksiyonu adı verilen herhangi bir iki yönlü hesaplanabilir fonksiyon olsun. Standart bir seçim

p(n,m)=(n+m)(n+m+1)2+n

Bir Bu yüzden, herhangi bir doğal göz önüne alındığında, bir bijection olduğunu ispat , biz hesaplayabilir , n , m , öyle ki p ( n , m ) = k .kn,mp(n,m)=k

Lambda terimlerini numaralandırmak için değişken adları için numaralandırmayı düzeltin: x0,x1,x2, .

Sonra, her doğal sayı , l a m b d a ( i )ilambda(i) özyineli olarak aşağıdaki şekilde tanımlanan :

  • Eğer da olduğu, izin j = i / 2 ve değişken dönüş x jij=i/2xj
  • Eğer garip, izin J = ( I - 1 ) / 2ij=(i1)/2
    • Eğer da olduğu, izin k = j / 2 ve bulmak n , m , öyle ki p ( n , m ) = K ; hesaplama N = 1 a m b d a ( n ) , M = 1 a m b d a ( m ) ; iade başvurusu ( N M )jk=j/2n,mp(n,m)=kN=lambda(n),M=lambda(m)(NM)
    • Eğer garip, izin k = ( j - 1 ) / 2 ve bulmak n , m , öyle ki p ( n , m ) = K ; M = l a m b d a ( m ) hesaplaması ; dönüş soyutlama ( λ x n . M )jk=(j1)/2n,mp(n,m)=kM=lambda(m)(λxn. M)

Bu program tüm lambda ifadeleri seti içeren aşağıdaki "cebirsel" bir eşleşme tarafından haklı :Λ

ΛN+(Λ2+N×Λ)

"lambda terimleri sözdizimsel olarak, 1) değişkenlerin (doğal olarak temsil edilen), 2) uygulamaların (iki lambda terimiyle yapılır) ve 3) soyutlama (bir çift değişken / doğal + lambda terimi) )".

Biz yinelemeli hesaplanabilir bijections uygulanır, göz önüne alındığında ( p ) ve K + KK üzerinde bir algoritma elde etme (hatta standart / tek bir).N2NpN+NN

Bu prosedür geneldir ve yukarıdaki dil ile benzer bir izomorfizm sağlayacak, bağlamsız bir dilbilgisi yoluyla üretilen hemen hemen her dil üzerinde çalışacaktır.


Vay canına, teşekkürler, bunun sahte kod olduğunu gösterebilir misin? Cs derecem olmadığı için bunu kesinlikle daha iyi anlardım.
Yasal Yığın

3
@LegitStack Peki, yukarıdaki sahte kod :) özyinelemeli bir işlev tanımlayabilir ve sonra kullanabilirsiniz . Önemsiz tek adım n , m'yi bulmaktır , öyle ki p ( n , m ) = k : bu, n , m ile n , m k arasındaki tüm çiftleri deneyerek yapılabilir (daha hızlı algoritmalar da mevcuttur)lambda(n)if n%2==0 ...n,mp(n,m)=kn,mn,mk
chi

1
a=12(8k+11),b=12a(a+1),n=bk,m=an

12

Yes. Take something that enumerates all possible ASCII strings. For each output, check if it is a valid lambda calculus syntax that defines a function; if not, skip it. (That check can be done.) That enumerates all lambda calculus functions.


5
Essentially, all problems like this are solved by invoking the typing monkey...
xuq01

5
Veya doğrudan lambda hesabı terimlerini numaralandırabilirsiniz. Her çıktı düzgün biçimlendirilmiş bir terim olduğundan rastgele dizelerden çok daha hızlı. Bu, yazma maymunlarını bir Shakespeare oyun jeneratörü ile değiştirmek gibi bir şey olurdu.
Dan D.

11

Daha önce de belirtildiği gibi, bu sadece bağlamdan bağımsız bir dilden terimleri numaralandırmaktır, bu yüzden kesinlikle yapılabilir. Ancak arkasındaki, analitik birleştiricilerin alanına giren daha ilginç matematik var.

İkili lambda hesabında terim sayma ve oluşturma makalesinde sayım probleminin tedavisi ve çok daha fazlası bulunmaktadır. İşleri daha basit hale getirmek için, ikili lambda calulus adlı bir şey kullanırlar , bu da De Bruijn endekslerini kullanarak lambda terimlerinin bir kodlamasıdır. , bu nedenle değişkenleri adlandırmanız gerekmez.

Bu makale aynı zamanda kendi nesil algoritmalarını uygulayan somut Haskell kodunu da içermektedir. Kesinlikle etkili bir şekilde mümkündür.

Julia'daki yaklaşımlarının bir uygulamasını yazdım .


7

Elbette. Bunları doğrudan lambda terimlerinin tanımına göre üretebiliriz.

Haskell'de önce veri türünü tanımlarız,

data LC a  =  Var  a                -- Constructor <type> <type> ...
           |  App (LC a) (LC a)     --
           |  Lam  a     (LC a)     --  ... alternatives ...

instance Show a => Show (LC a)      -- `LC a` is in Show if `a` is in Show, and
  where
    show (Var i)    =  [c | c <- show i, c /= '\'']
    show (App m n)  =  "("  ++ show m       ++ " " ++ show n ++ ")"
    show (Lam v b)  =  "(^" ++ show (Var v) ++ "." ++ show b ++ ")"

ve sonra bir fuar (er) kullanımı ile join,

lambda :: [a] -> [LC a]
lambda vars  =  terms 
  where
  terms  =  fjoin [ map Var vars ,
                    fjoin [ [App t s | t <- terms] | s <- terms ] ,
                    fjoin [ [Lam v s | v <- vars ] | s <- terms ] ]

  fjoin :: [[a]] -> [a]
  fjoin xs  =  go [] xs             -- fairer join
      where 
      go [] []  =  []
      go a  b   =  reverse (concatMap (take 1) a) ++ go 
                       (take 1 b ++ [t | (_:t) <- a]) (drop 1 b)

onları sadece numaralandırıyoruz, örneğin

> take 20 $ lambda "xyz"
[x,y,(x x),z,(y x),(^x.x),(x y),(^y.x),((x x) x),(^x.y),(y y),(^z.x),(x (x x)),
 (^y.y),(z x),(^x.(x x)),((x x) y),(^z.y),(y (x x)),(^y.(x x))]

> take 5 $ drop 960 $ lambda "xyz"
[(((x x) y) (z x)),(^y.(^x.((x x) (x x)))),((^x.(x x)) (^x.(x x))),(^x.((^z.x) 
 y)),((z x) ((x x) y))]

Bak, ünlü Ω=(λx.xx)(λx.xx) terim orada yukarıdan çok aşağı değil!

fjoineşdeğerdir Monad Omega 'nın diagonal.


0

Ben normal bir ifade örnek dizeleri oluşturabilir çevrimiçi bir araç rastladım: https://www.browserling.com/tools/text-from-regex . Bunun gibi bir şey girerek çok sayıda örnek lambda terimi oluşturabilirsiniz:

(\( (lambda \w\. )* \w+ \))* 

Elbette, rastgele iç içe yerleştirme düzeylerine sahip terimler elde etmek için, bir dili tanımlamak için normal bir ifadeden daha açıklayıcı bir araç olan bağlamsız bir gramer kullanmanız gerekecektir. Bağlamdan bağımsız bir dilbilgisi tanımına dayalı örnek dil cümleleri oluşturmak için mevcut bir araca rastlamadım, ancak birinin oluşturulamamasının bir nedeni yok.


2
λ-termler normal ifadeler değildir (not ettiğiniz gibi). Yeni başlayanların sorusunu bu şekilde cevaplamak zararlıdır çünkü önemli bir ayrımı gizler (bağlamdan bağımsız gramerler ve düzenli ifadeler arasında).
Andrej Bauer
Sitemizi kullandığınızda şunları okuyup anladığınızı kabul etmiş olursunuz: Çerez Politikası ve Gizlilik Politikası.
Licensed under cc by-sa 3.0 with attribution required.