BEARBEITEN: Ein Kommentar oben hat das fehlende Stück zur Verfügung gestellt. Einige Leute spielen absichtlich mit unvollständigen Sprachen. Solche Sprachen interessieren mich ausdrücklich nicht. Eine wirklich brauchbare Sprache, die nicht vollständig ist, ist verrückt schwer zu entwerfen. Der ganze Rest geht auf das ein, was passiert, wenn versucht wird, diese Theoreme auf eine vollständige Sprache anzuwenden.
Falsch!
function f(a): forall t: Type, t->t
function g(a): forall t: Type, t->t
return (a is g) ? f : a
return a is f ? g : a
Dabei is
vergleicht der Operator zwei Variablen auf Referenzidentität. Das heißt, sie enthalten den gleichen Wert. Kein äquivalenter Wert, gleicher Wert. Funktionen f
und g
sind per definitionem äquivalent, aber sie sind nicht gleich.
Wenn diese Funktion selbst übergeben wird, gibt sie etwas anderes zurück. Andernfalls wird die Eingabe zurückgegeben. Das etwas andere hat den gleichen Typ wie sich selbst, daher kann es ersetzt werden. Mit anderen Worten, f
ist nicht die Identität, weil f(f)
zurückkehrt g
, während die Identität zurückkehren würde f
.
Damit der Satz gilt, muss er die lächerliche Fähigkeit annehmen, zu reduzieren
function cantor(n, <z, a>) : forall t: t: Type int, <int, t> -> <int, t>
return n > 1 ? cantor((n % 2 > 0) ? (n + 1) : n / 2, <z + 1, a>) : <z, a>
return cantor(1000, <0, a>)[1]¹
Wenn Sie davon ausgehen möchten, dass Sie davon ausgehen können, dass die viel einfachere Typinferenz verarbeitet werden kann.
Wenn wir versuchen, die Domäne einzuschränken, bis der Satz gilt, müssen wir sie schrecklich weit einschränken.
- Pure Functional (kein veränderlicher Zustand, kein IO). OK, damit kann ich leben. Viel Zeit wollen wir Beweise über Funktionen laufen lassen.
- Leere Standardbibliothek. meh.
- Nein
raise
und nein exit
. Jetzt werden wir gezwungen.
- Es gibt keinen Bodentyp.
- Die Sprache hat eine Regel, die es dem Compiler ermöglicht, die unendliche Rekursion zu reduzieren, indem angenommen wird, dass sie beendet werden muss. Der Compiler darf triviale unendliche Rekursionen ablehnen.
- Der Compiler kann fehlschlagen, wenn etwas angezeigt wird, das in keiner Weise bewiesen werden kann.² Jetzt kann die Standardbibliothek keine Funktionen als Argumente annehmen. Boo.
- Es gibt keine
nil
. Das wird langsam problematisch. Wir haben keine Möglichkeiten mehr, mit 1 / 0.³ umzugehen
- Die Sprache kann keine Verzweigungstypen ableiten und hat keine Außerkraftsetzung dafür, wann der Programmierer eine Typabweichung nachweisen kann, die die Sprache nicht kann. Das ist ziemlich schlimm.
Die Existenz der beiden letzten Einschränkungen hat die Sprache lahmgelegt. Während Turing noch vollständig ist, besteht die einzige Möglichkeit, allgemeine Aufgaben zu lösen, darin, eine innere Plattform zu simulieren, die eine Sprache mit geringeren Anforderungen interpretiert.
¹ Wenn Sie glauben, dass der Compiler diesen herleiten kann, probieren Sie diesen aus
function fermat(z) : int -> int
function pow(x, p)
return p = 0 ? 1 : x * pow(x, p - 1)
function f2(x, y, z) : int, int, int -> <int, int>
left = pow(x, 5) + pow(y, 5)
right = pow(z, 5)
return left = right
? <x, y>
: pow(x, 5) < right
? f2(x + 1, y, z)
: pow(y, 5) < right
? f2(2, y + 1, z)
: f2(2, 2, z + 1)
return f2(2, 2, z)
function cantor(n, <z, a>) : forall t: t: Type int, <int, t> -> <int, t>
return n > 1 ? cantor((n % 2 > 0) ? (n + 1) : n / 2, <z + 1, a>) : <z, a>
return cantor(fermat(3)[0], <0, a>)[1]
² Der Beweis, dass der Compiler dies nicht kann, hängt von der Blendung ab. Wir können mehrere Bibliotheken verwenden, um sicherzustellen, dass der Compiler die Schleife nicht gleichzeitig sehen kann. Außerdem können wir immer etwas konstruieren, bei dem das Programm funktionieren würde, das jedoch nicht kompiliert werden konnte, da der Compiler die Induktion im verfügbaren Speicher nicht ausführen kann.
³ Jemand denkt, Sie können diesen Rückgabewert auf Null setzen, ohne dass willkürliche generische Typen den Wert Null zurückgeben. Das zahlt eine fiese Strafe, für die ich keine wirksame Sprache gesehen habe, die es bezahlen kann.
function f(a, b, c): t: Type: t[],int,int->t
return a[b/c]
darf nicht kompilieren. Das grundlegende Problem ist, dass die Laufzeit-Array-Indizierung nicht mehr funktioniert.