Wie funktionieren Ausnahmen in Haskell?

86

In GHCi:

Prelude> error (error "")
*** Exception: 
Prelude> (error . error) ""
*** Exception: *** Exception: 

Warum ist die erste keine verschachtelte Ausnahme?

Daniel Wagner
quelle
9
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 of
   1 -> 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 )

Don Stewart
quelle
1
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.
Ben Millwood