Was ist der Unterschied zwischen undefined in Haskell und null in Java?
Frage
Beide sind Begriffe, deren Typ ist der Schnittpunkt aller Art (unbewohnt). Beide können ohne versagen, bis man versucht in Code herumgereicht werden, um sie zu bewerten. Der einzige Unterschied, den ich sehen kann, ist, dass in Java gibt es eine Lücke, die null
ermöglicht genau eine Operation ausgewertet werden, der Bezugsgleichheitsvergleich ist (==
) - während in Haskell undefined
überhaupt nicht bewertet werden kann, ohne dass ein Wurf Ausnahme. Ist dies der einzige Unterschied?
Bearbeiten
Was ich wirklich zu bekommen, mit dieser Frage versuchen, ist, warum wurde einschließlich null
in Java solchen scheinbar schlechte Entscheidung, und wie Haskell es zu entkommen? Es scheint mir, dass das eigentliche Problem ist, dass man etwas tun kann, nützlich mit null
, nämlich können Sie es überprüfen nullness . Weil Sie erlaubt sind, dies zu tun, ist es Standard-Konvention passiert um Nullwerte in Code worden und hat sie „kein Ergebnis“ geben statt „ein logischer Fehler in diesem Programm ist“. Während in Haskell, gibt es keine Möglichkeit, wenn ein Ausdruck auswertet nach unten zu überprüfen, ohne es zu bewerten und das Programm explodiert, so dass es nie in einer solchen Art und Weise verwendet werden könnten „kein Ergebnis“ anzuzeigen. Stattdessen wird man Gebrauch etwas wie Maybe
gezwungen.
Sorry, wenn es scheint, wie ich spiele schnell und locker mit dem Begriff „bewerten“ ... Ich versuche hier eine Analogie zu ziehen und Probleme, es genau formulieren. Ich denke, das ist ein Zeichen dafür, dass die Analogie ungenau ist.
Lösung
Was ist der Unterschied zwischen undefined in Haskell und null in Java?
Ok, kommen wir zurück nach oben ein wenig.
"undefiniert" in Haskell ein Beispiel für einen "bottom" Wert ist (bezeichnet ?). Ein solcher Wert steht für eine beliebige undefiniert, stecken bleiben oder Teilzustand im Programm.
Viele verschiedenen Formen der Unterseite vorhanden sein: Nicht-Abschluss Schleifen, Ausnahmen, Mustererkennung Ausfälle - im Grunde jeden Zustandes in dem Programm, das in gewissem Sinne nicht definiert ist. Der Wert undefined :: a
ist ein kanonisches Beispiel für einen Wert, legt das Programm in einem undefinierten Zustand.
undefined
selbst ist nicht ganz Besonderes - es ist nicht verdrahtet - und Sie können Haskells undefined
kein Grundrentier Ausdruck umzusetzen. Z.B. dies ist eine gültige Implementierung von undefined
:
> undefined = undefined
oder Verlassen sofort (der alten Gofer Compiler diese Definition verwendet):
> undefined | False = undefined
Die primäre Eigenschaft von unten ist, dass, wenn ein Ausdruck auswertet nach unten, das gesamte Programm nach unten auswerten wird. Das Programm ist in einem undefinierten Zustand
Warum würden Sie einen solchen Wert wollen? Nun, in einer faulen Sprache, können Sie oft Strukturen oder Funktionen manipulieren, die unteren Werte speichern, ohne das Programm zu sein selbst unten.
z. eine Liste von Endlosschleifen ist perfekt cromulent:
> let xs = [ let f = f in f
, let g n = g (n+1) in g 0
]
> :t xs
xs :: [t]
> length xs
2
Ich kann nicht viel tun, mit den Elementen der Liste:
> head xs
^CInterrupted.
Diese Manipulation der unendlichen Sachen gehört, warum Haskells so Spaß und ausdrucksstark. Ein Ergebnis von Faulheit ist Haskell zahlt besonders aufmerksam auf bottom
Werte.
Doch klar, gilt das Konzept des Bodens ebenso gut auf Java oder irgendeine (nicht-gesamt) Sprache. In Java gibt es viele Ausdrücke, die Ausbeute „unten“ Werte:
- einen Verweis gegen null zu vergleichen (obwohl Note, nicht
null
selbst, die wohldefiniert); - Division durch Null;
- out-of-bounds Ausnahmen;
- eine Endlosschleife, etc.
Sie haben einfach nicht die Möglichkeit, eine andere Unterseite zu ersetzen sehr leicht, und der Java-Compiler tun nicht viel Grund, sich um Grundwerte. Allerdings sind solche Werte gibt.
Insgesamt
- Dereferenzieren eines
null
Wert in Java ist ein Ausdruck, der einen bestimmten Minimalwert in Java ergibt; - der
undefined
Wert in Haskell ist ein generischer Bodenrentier Ausdruck, der überall ist ein Grundwert in Haskell erforderlich verwendet werden kann.
Das ist, wie sie sind ähnlich.
Postscript
In Bezug auf die Frage der null
selbst: warum ist es schlechter Stil betrachtet
- Erstens Java
null
ist im wesentlichen äquivalent zu Hinzufügen eines implizitenMaybe a
für jede Arta
in Haskell . -
null
Dereferenzieren entspricht Musteranpassung nur für den FallJust
:f (Just a) = ... a ...
Also, wenn der übergebene Wert Nothing
ist (in Haskell) oder null
(in Java), erreicht das Programm in einen undefinierten Zustand. Das ist schlecht. Ihr Programm stürzt
Also, durch Zugabe von null
zu alle Typ, haben Sie gerade gemacht es viel einfacher bottom
Werte zufällig zu schaffen - die Typen nicht mehr helfen Sie. Ihre Sprache ist nicht mehr hilft, dass bestimmte Art von Fehlern zu vermeiden, und das ist schlecht.
Natürlich sind auch andere Grundwerte immer noch da: Ausnahmen (wie undefined
) oder Endlosschleifen. Hinzufügen eines neuen möglichen Fehlermodus zu jeder Funktion - dereferencing null
- macht es nur einfacher, Programme zu schreiben, dass crash
Andere Tipps
ist Ihre Beschreibung nicht ganz richtig. Du sagst null
kann nicht ausgewertet werden. Da jedoch Java eine eifrige Sprache ist, dies, dass f(null)
bedeuten würde, eine NPE egal werfen würde, was die Definition von f
ist (weil Methodenargumente, bevor die Methode läuft immer ausgewertet werden).
Der einzige Grund, dass Sie undefined
in Haskell passieren um können eine Ausnahme, ohne dabei ist, dass Haskell faul ist und nicht ausgewertet Argumente nur bei Bedarf.
Ein weiterer Unterschied zwischen undefined und null ist, dass undefined
ein einfacher Wert wird in der Standardbibliothek definiert. Wenn es nicht in der Standardbibliothek definiert wurden Sie konnte es selbst definieren (von myUndefined = error "My Undefined
zum Beispiel das Schreiben).
In Java null
ist ein Schlüsselwort. Wenn es kein null
Stichwort, würden Sie nicht in der Lage sein zu definieren, es (tut das Äquivalent der Haskell-Definition, das heißt Object myNull = throw(new Exception())
, würde nicht funktionieren, weil der Ausdruck genau dort ausgewertet werden würde).