Dies ist eine Transformation, die GHC vornehmen darf: "Ich bin der Compiler, der selbst arbeitet, und alle _ | _s sind mir gleich." Fragen Sie nach den Implementierungsdetails, mit denen diese beiden Zeilen unterschiedlich kompiliert werden?
Shachaf
3
errorist etwas Besonderes und kein wirklicher Ausnahmemechanismus. Für echte, fangbare Ausnahmen siehe ErrorMonade.
Cat Plus Plus
1
Beachten Sie zum Beispiel, dass (\f g x -> f (g x)) error error ""sich das anders verhält (.) error error "", obwohl diese Funktion äquivalent zu ist (.). Vielleicht hat es mit den Optimierungsflags zu tun, mit denen Prelude kompiliert wurde.
Shachaf
5
Auch iterate error "" !! nund das genial fix error.
Vitus
9
Ich tue das immer so error = errorund programmiere entsprechend.
Gabriel Gonzalez
Antworten:
101
Die Antwort ist, dass dies die (etwas überraschende) Semantik von ist ungenauer Ausnahmen ist
Wenn gezeigt werden kann, dass reiner Code zu einer Reihe von Ausnahmewerten ausgewertet wird (dh der Wert von erroroder undefinedund explizit nicht die Art der in IO generierten Ausnahmen ), ermöglicht die Sprache die Rückgabe eines beliebigen Werts dieser Menge. Außergewöhnliche Werte in Haskell sind eher ähnlichNaN Gleitkomma-Code als auf Kontrollfluss basierenden Ausnahmen in imperativen Sprachen.
Ein gelegentliches Problem für fortgeschrittene Haskeller ist ein Fall wie:
case x of1-> error "One"_-> error "Not one"
Da der Code eine Reihe von Ausnahmen ergibt, kann GHC eine auswählen. Wenn Optimierungen aktiviert sind, wird dies möglicherweise immer als "Nicht einer" ausgewertet.
Warum machen wir das? Weil wir sonst die Bewertungsreihenfolge der Sprache übermäßig einschränken würden, z. B. müssten wir ein deterministisches Ergebnis festlegen für:
f (error "a")(error "b")
indem beispielsweise verlangt wird, dass es von links nach rechts ausgewertet wird, wenn Fehlerwerte vorhanden sind. Sehr un-Haskelly!
Da wir die Optimierungen, die an unserem Code vorgenommen werden können, nicht nur zur Unterstützung lähmen wollen error , besteht die Lösung darin, anzugeben, dass das Ergebnis eine nicht deterministische Auswahl aus dem Satz außergewöhnlicher Werte ist: ungenaue Ausnahmen! In gewisser Weise werden alle Ausnahmen zurückgegeben und eine ausgewählt.
Normalerweise ist es Ihnen egal - eine Ausnahme ist eine Ausnahme - es sei denn, Sie interessieren sich für die Zeichenfolge in der Ausnahme. In diesem Fall ist die Verwendung errorzum Debuggen sehr verwirrend.
Referenzen: Eine Semantik für ungenaue Ausnahmen , Simon Peyton Jones, Alastair Reid, Tony Hoare, Simon Marlow, Fergus Henderson. Entwurf und Implementierung von Proc-Programmiersprachen (PLDI'99), Atlanta. ( PDF )
Ich verstehe, dass GHC eine der Ausnahmen auswählt, die auftreten können. In Ihrem "Fall" -Beispiel kann die Ausnahme "Nicht eine" für eine Eingabe von 1 nicht auftreten, daher würde ich dies immer noch als Fehler klassifizieren.
Peaker
8
@Peaker dead code elim - Der Optimierer muss nicht auf x schauen, um zu sehen, dass ein Fehler das Ergebnis ist. Alle Zweige erzeugen den "gleichen" Wert, sodass der Eingabewert vollständig ignoriert werden kann. Kein Fehler, unter ungenauen Ausnahmen!
Don Stewart
1
@lpsmith: Ich denke, alle Ausnahmetypen sind ungenau (wenn sie mit ausgelöst werden throw) und mit denen Sie eine Ausnahme deterministisch auslösen können throwIO.
FunctorSalad
3
@Peaker Ich denke du hast recht. Ich denke nicht, dass ghc diesen Ausdruck optimieren sollte, wenn sie sich an die Regeln halten wollen, die im ungenauen Ausnahmepapier festgelegt sind.
August
3
Was die ungenauen Ausnahmen Papier nicht scheinen zu sagen , dass , wenn der Fall scrutinee ein Fehlerwert ist, dann Werte Fehler von den Zweigen zurückgeführt werden können. case error "banana" of (x:xs) -> error "bonobo"Kann dir also geben * Exception: bonobo.
error
ist etwas Besonderes und kein wirklicher Ausnahmemechanismus. Für echte, fangbare Ausnahmen sieheError
Monade.(\f g x -> f (g x)) error error ""
sich das anders verhält(.) error error ""
, obwohl diese Funktion äquivalent zu ist(.)
. Vielleicht hat es mit den Optimierungsflags zu tun, mit denen Prelude kompiliert wurde.iterate error "" !! n
und das genialfix error
.error = error
und programmiere entsprechend.Antworten:
Die Antwort ist, dass dies die (etwas überraschende) Semantik von ist ungenauer Ausnahmen ist
Wenn gezeigt werden kann, dass reiner Code zu einer Reihe von Ausnahmewerten ausgewertet wird (dh der Wert von
error
oderundefined
und explizit nicht die Art der in IO generierten Ausnahmen ), ermöglicht die Sprache die Rückgabe eines beliebigen Werts dieser Menge. Außergewöhnliche Werte in Haskell sind eher ähnlichNaN
Gleitkomma-Code als auf Kontrollfluss basierenden Ausnahmen in imperativen Sprachen.Ein gelegentliches Problem für fortgeschrittene Haskeller ist ein Fall wie:
Da der Code eine Reihe von Ausnahmen ergibt, kann GHC eine auswählen. Wenn Optimierungen aktiviert sind, wird dies möglicherweise immer als "Nicht einer" ausgewertet.
Warum machen wir das? Weil wir sonst die Bewertungsreihenfolge der Sprache übermäßig einschränken würden, z. B. müssten wir ein deterministisches Ergebnis festlegen für:
indem beispielsweise verlangt wird, dass es von links nach rechts ausgewertet wird, wenn Fehlerwerte vorhanden sind. Sehr un-Haskelly!
Da wir die Optimierungen, die an unserem Code vorgenommen werden können, nicht nur zur Unterstützung lähmen wollen
error
, besteht die Lösung darin, anzugeben, dass das Ergebnis eine nicht deterministische Auswahl aus dem Satz außergewöhnlicher Werte ist: ungenaue Ausnahmen! In gewisser Weise werden alle Ausnahmen zurückgegeben und eine ausgewählt.Normalerweise ist es Ihnen egal - eine Ausnahme ist eine Ausnahme - es sei denn, Sie interessieren sich für die Zeichenfolge in der Ausnahme. In diesem Fall ist die Verwendung
error
zum Debuggen sehr verwirrend.Referenzen: Eine Semantik für ungenaue Ausnahmen , Simon Peyton Jones, Alastair Reid, Tony Hoare, Simon Marlow, Fergus Henderson. Entwurf und Implementierung von Proc-Programmiersprachen (PLDI'99), Atlanta. ( PDF )
quelle
throw
) und mit denen Sie eine Ausnahme deterministisch auslösen könnenthrowIO
.case error "banana" of (x:xs) -> error "bonobo"
Kann dir also geben* Exception: bonobo
.