2016-04-24 17 views
0

Warum kann ich Wert nicht definiert in Haskell verwenden? Ich meine, dass im Falle:undefined Wert in Haskell

>let t = undefinded 
>if t == undefined then "undefined" else "not undefined" 

Es wirft *** Exception: Prelude.undefined Kann ich nicht undefinierten Wert in einer solchen Art und Weise verwenden?

+2

Nicht definiert ist ein bisschen wie ein Fehlerwert. Wenn Sie es auswerten, wird ein Fehler ausgegeben. Es ist * kein * Datenwert. – AJFarmar

+0

Haskell erlaubt keinen Nullzeiger/Nullwert: Er wurde entworfen, um einen [Milliarden Dollar Fehler] (https://en.wikipedia.org/wiki/Null_pointer#History) zu vermeiden. – chi

Antwort

4

Dies ist Prelude-Implementierung der undefined Funktion:

undefined = error "Prelude.undefined" 

So versucht undefined zu bewerten wird eine Ausnahme jedes Mal erhöhen. Durch den Vergleich von t mit undefined erzwingen Sie diese Bewertung.

Beachten Sie, dass sich undefined auf eine Berechnung bezieht, die nie erfolgreich abgeschlossen wird, nicht auf einen nicht bekannten Wert (was die Bedeutung von undefined in JavaScript zum Beispiel bedeutet; verwechseln Sie diese beiden nicht, sie sind unterschiedliche Dinge).

+0

Gibt es einige undef-Wert für String, Integer ...? –

+6

@HaskellFun Nein, wenn die Wahrscheinlichkeit besteht, dass eine bestimmte Funktion kein Ergebnis liefert, sollten Sie den Typ "Maybe" verwenden. – sepp2k

1

undefined ist weitgehend nur eine Standardmethode, um einen “ unteren Wert ” zu generieren. Der untere Wert (⊥) ist der einzige Wert in alle& Dolch; Typ, so dass Sie

Prelude> undefined :: Int 
*** Exception: Prelude.undefined 
Prelude> undefined :: Double 
*** Exception: Prelude.undefined 
Prelude> undefined :: String 
"*** Exception: Prelude.undefined 
Prelude> undefined :: IO [Bool] 
*** Exception: Prelude.undefined 

Neben den Ausnahmemeldungen tun können, diese sind äquivalent zu jedem “ benutzerdefinierten ” Tiefstwert, wie

undefined' :: a 
undefined' = undefined' -- this definition creates an infinite loop! 

Diesmal ich erhalte keine Fehlermeldung – ich habe manuell abbrechen:

Prelude> undefined' :: Int 
^CInterrupted. 

Tatsächlich ist die Haskell-Standard garantiert nichts davon! Jede Berechnung, die niemals mit einem “ richtigen Wert ” des angegebenen Typs endet, wird als Wert ⊥ betrachtet. Da Sie in general not prove können, dass eine Berechnung nicht beendet wird, ist es nicht möglich, Haskell zu fragen, ob ein bestimmter Wert ⊥/undefined ist.

Wenn Sie Werte haben wollen, die explizit (und testbar) Nicht-Werte haben können, dann schreiben Sie den Typ in eine Maybe!


& dolch; Außer in unboxed types, aber das sind eine fortgeschrittene Low-Level-Sache, die meist für die Optimierung verwendet wird.

0

Das Muster Sie suchen ist:

let t = Nothing :: Maybe String 
case t of 
    Nothing -> "undefined" 
    Just v -> "defined with value: " ++ v 
3

Vielleicht analog Sie Argumentation, zu denken, dass „unbestimmt“ ist das Haskell Äquivalent eines void-Zeiger oder NULL-Verweis in einer OO-Sprache. Es ist nicht. In Haskell ist ein undefinierter Wert einfach ein Fehler, der darauf wartet, zu passieren.

Wenn Sie einen optionalen Wert wünschen (die Art von Dingen, für die Sie in anderen Sprachen eine Nullreferenz verwenden würden), dann möchten Sie vielleicht. So ist zum Beispiel ein Maybe Int entweder "Nothing" oder "Just 5".So hat zum Beispiel die „Lookup“ -Funktion

lookup :: Eq a => a -> [(a, b)] -> Maybe b 

geben Dieses sagt, dass es die Dinge in einer Liste von Paaren schaut auf das Schlüsselelement durch Anpassung (Typ „a“) ​​und gibt dann das zweite Element in dem Paar (Geben Sie "b" ein). Natürlich kann es den Schlüssel nicht finden, in diesem Fall gibt es "Nichts" zurück.

lookup "foo" [("foo", 1), ("bar, 2)]  gives  Just 1 
lookup "wib" [("foo", 1), ("bar, 2)]  gives  Nothing 

Um das Ergebnis aus dem bekommen Sie verwenden Pattern-Matching "Vielleicht":

case lookup myKey theTable of 
    Just result -> putStrLn $ "Found " ++ show result 
    Nothing -> putStrLn "Key not found" 

Sie können auch die Verwendung "vielleicht" und "fromMaybe" Funktionen in Data.Maybe. Wenn Sie absolut sicher sind, dass der Wert wirklich da ist, können Sie auch "fromJust" verwenden, aber Sie müssen sehr sicher sein, und selbst dann sollten Sie eine explizite Argument für Nothing haben, so dass Sie eine sinnvolle Fehlermeldung geben können, wenn Sie entpuppen sich als falsch.

Edit: Erklärung, warum wir es tun diese Weise

Der Grund, dass Haskell nicht null Referenzen hat wie andere Sprachen ist, dass sie von Natur aus mehrdeutig sind. Wenn irgendein Wert "Null" sein kann, können Sie nicht sicher sein, ob Sie nach Null suchen sollten oder nicht. Im obigen "Lookup" -Beispiel macht es also den Rückgabetyp "Maybe b" eindeutig, und außerdem, wenn Sie vergessen zu checken, dann sagt Ihnen der Compiler. Wenn "Lookup" hingegen einen Verweis zurückgibt, der null sein könnte, wie soll der Aufrufer das wissen? Was passiert, wenn eines der Argumente für "Lookup" ebenfalls null ist? Wäre das ein Fehler? Wenn Sie NULL-Referenzen haben, können Sie den Code nur lesen oder hoffen, dass er in die Dokumentation aufgenommen wurde.