Lambda-Kalkülgenerator

10

Ich weiß nicht, wo ich diese Frage sonst stellen soll, ich hoffe, das ist ein guter Ort.

Ich bin nur neugierig zu wissen, ob es möglich ist, einen Lambda-Kalkülgenerator herzustellen. Im Wesentlichen eine Schleife, die bei unendlicher Zeit jede mögliche Lambda-Kalkülfunktion erzeugt. (wie in Form einer Zeichenfolge).

Da der Lambda-Kalkül so einfach ist und nur wenige Elemente in seiner Notation enthält, dachte ich, dass es möglich (wenn auch nicht sehr nützlich) sein könnte, alle möglichen Kombinationen dieser Notationselemente zu erzeugen, beginnend mit den einfachsten Kombinationen, und dadurch jedes mögliche Lambda zu erzeugen Kalkülfunktion.

Natürlich weiß ich fast nichts über Lambda-Kalkül, daher habe ich keine Ahnung, ob dies wirklich möglich ist.

Ist es? Wenn ja, ist es ziemlich einfach, wie ich es mir vorgestellt habe, oder ist es technisch möglich, aber so schwierig, dass es praktisch unmöglich ist?

PS. Ich spreche nicht von Beta-reduzierten Funktionen, ich spreche nur von jeder gültigen Notation jeder Lambda-Kalkülfunktion.

Legit Stack
quelle

Antworten:

19

Sicher, dies ist eine Standardcodierungsübung.

Zunächst sei eine bijektiv berechenbare Funktion, die als Paarungsfunktion bezeichnet wird. Eine Standardauswahl istp:N2N

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

Man kann beweisen, dass dies eine Bijektion ist, also können wir bei jedem natürlichen so berechnen dass .n , mkn,mp(n,m)=k

Um Lambda-Begriffe aufzulisten, korrigieren Sie die Aufzählung der Variablennamen: .x0,x1,x2,

Dann wird für jede natürliche Zahl , Drucken , definiert rekursiv wie folgt:l a m b d a ( i )ilambda(i)

  • Wenn ist, sei und gebe die Variablej = i / 2 x jij=i/2xj
  • wenn ungerade ist, seij = ( i - 1 ) / 2ij=(i1)/2
    • wenn ist, sei und finde so, dass ; berechne ; Rückantragk = 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/2n,mp(n,m)=kN=lambda(n),M=lambda(m)(NM)
    • wenn ungerade ist, sei und finde so, dass ; berechne ; Abstraktion zurückgebenjk=(j1)/2n,mp(n,m)=kM=lambda(m)(λxn. M)

Dieses Programm wird durch die folgende "algebraische" Bijektion gerechtfertigt, die die Menge aller Lambda-Terme :Λ

ΛN+(Λ2+N×Λ)

Dies wird gelesen als "die Lambda-Terme sind syntaktisch die disjunkte Vereinigung von 1) Variablen (dargestellt als natürlich), 2) Anwendungen (gemacht durch zwei Lambda-Terme) und 3) Abstraktion (ein Paar Variable / natürlich + Lambda-Term ) ".

Angesichts dessen wenden wir rekursiv berechenbare Bijektionen ( ) und (die Standard-Gerade / Ungerade) an, um den obigen Algorithmus zu erhalten.N2NpN+NN

Diese Prozedur ist allgemein und funktioniert mit fast jeder Sprache, die durch eine kontextfreie Grammatik erzeugt wird, die einen ähnlichen Isomorphismus wie die oben beschriebene liefert.

Chi
quelle
Wow, danke, ist es möglich, dass Sie darstellen, dass dies Pseudocode ist? Ich würde das definitiv besser verstehen, da ich keinen CS-Abschluss habe.
Legit Stack
3
@LegitStack Nun, das obige ist Pseudocode :) Sie können eine rekursive Funktion und dann verwenden . Der einzige nicht triviale Schritt besteht darin, so zu finden, dass : Dies kann erreicht werden, indem alle Paare mit ausprobiert werden (es gibt auch schnellere Algorithmen)n , m p ( n , m ) = k n , m n , m klambda(n)if n%2==0 ...n,mp(n,m)=kn,mn,mk
chi
1
Tatsächlich kann laut Wikipedia die Umkehrung dieser bestimmten Paarungsfunktion über . a=12(8k+11),b=12a(a+1),n=bk,m=an
LegionMammal978
12

Ja. Nehmen Sie etwas, das alle möglichen ASCII-Zeichenfolgen auflistet. Überprüfen Sie für jede Ausgabe, ob es sich um eine gültige Lambda-Kalkülsyntax handelt, die eine Funktion definiert. Wenn nicht, überspringen Sie es. (Diese Überprüfung kann durchgeführt werden.) Damit werden alle Lambda-Kalkülfunktionen aufgelistet.

DW
quelle
4
Im Wesentlichen werden alle Probleme wie diese durch Aufrufen des
Tippaffen
5
Oder Sie können Lambda-Kalkülbegriffe direkt aufzählen. Viel schneller als zufällige Zeichenfolgen, da jede Ausgabe ein richtig formatierter Begriff ist. Das wäre, als würde man die tippenden Affen durch einen Shakespeare-Spielgenerator ersetzen.
Dan D.
11

Wie bereits erwähnt, werden hier nur Begriffe aus einer kontextfreien Sprache aufgezählt, die definitiv machbar sind. Dahinter steckt jedoch eine interessantere Mathematik, die sich mit der anlytischen Kombinatorik befasst.

Das Papier Zählen und Generieren von Begriffen in der binären Lambda-Rechnung enthält eine Behandlung des Aufzählungsproblems und vieles mehr. Zur Vereinfachung verwenden sie den so genannten binären Lambda-Calulus , bei dem es sich lediglich um eine Codierung von Lambda-Begriffen mit De Bruijn-Indizes handelt , sodass Sie keine Variablen benennen müssen.

Dieses Papier enthält auch konkreten Haskell-Code, der den Generierungsalgorithmus implementiert. Es ist definitiv effektiv möglich.

Ich habe zufällig eine Implementierung ihres Ansatzes in Julia geschrieben.

phipsgabler
quelle
5

Sicher. Wir können sie direkt gemäß der Definition von Lambda-Begriffen erzeugen.

In Haskell definieren wir zuerst den Typ,

data LC a = Var a | App (LC a) (LC a) | Lam a (LC a)

instance Show a => Show (LC a) 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 ++ ")"

und dann mit

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 (take 1 xs) (drop 1 xs)      -- fair join
      where 
      go [] [] = []
      go a  b  = reverse (concatMap (take 1) a) ++ go 
                     (take 1 b ++ [t | (_:t) <- a]) (drop 1 b)

wir zählen sie nur auf, wie z

> 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))]

Schauen Sie, der berühmte Begriff ist dort nicht weit von oben!Ω=(λx.xx)(λx.xx)

fjoinentspricht Omega Monade ‚s diagonal.

Will Ness
quelle
0

Ich bin online auf ein Tool gestoßen, das Beispielzeichenfolgen aus einem regulären Ausdruck generieren kann: https://www.browserling.com/tools/text-from-regex . Sie können viele Beispiel-Lambda-Begriffe generieren, indem Sie Folgendes eingeben:

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

Um Begriffe mit beliebigen Verschachtelungsebenen zu erhalten, müssen Sie natürlich eine kontextfreie Grammatik verwenden, die ein aussagekräftigeres Werkzeug zum Definieren einer Sprache darstellt als ein regulärer Ausdruck. Ich bin nicht auf ein vorhandenes Tool zum Generieren von Beispielsprachensätzen gestoßen, das auf einer kontextfreien Grammatikdefinition basiert, aber es gibt keinen Grund, warum man keine erstellen könnte.

Martin
quelle
2
Die Terme sind keine regulären Ausdrücke (wie Sie bemerken). Es ist schädlich, die Frage eines Anfängers auf diese Weise zu beantworten, da dadurch eine wichtige Unterscheidung (nämlich zwischen kontextfreien Grammatiken und regulären Ausdrücken) verdeckt wird. λ
Andrej Bauer