Okay, erste Regel zur Fehlerbehandlung in Haskell: Niemals verwendenerror .
Es ist einfach in jeder Hinsicht schrecklich. Es existiert nur als Akt der Geschichte und die Tatsache, dass Prelude es benutzt, ist schrecklich. Benutze es nicht.
Die einzig denkbare Zeit, die Sie nutzen könnten, ist, wenn etwas so schrecklich ist, dass etwas mit dem eigentlichen Realitätsgefüge nicht in Einklang stehen muss, wodurch das Ergebnis Ihres Programms in Frage gestellt wird.
Nun ist die Frage wird Maybevs Either. Maybeeignet sich gut für etwas head, das einen Wert zurückgeben kann oder nicht, aber es gibt nur einen möglichen Grund für das Scheitern. Nothingsagt so etwas wie "es ist kaputt gegangen und du weißt schon warum". Einige würden sagen, es deutet auf eine Teilfunktion hin.
Die robusteste Form der Fehlerbehandlung ist Either+ ein Fehler-ADT.
Zum Beispiel habe ich in einem meiner Hobby-Compiler so etwas wie
data CompilerError = ParserError ParserError
| TCError TCError
...
| ImpossibleError String
data ParserError = ParserError (Int, Int) String
data TCError = CouldntUnify Ty Ty
| MissingDefinition Name
| InfiniteType Ty
...
type ErrorM m = ExceptT CompilerError m -- from MTL
Jetzt definiere ich eine Reihe von Fehlertypen und verschachtele sie so, dass ich einen herrlichen Fehler der obersten Ebene habe. Dies kann ein Fehler in jeder Phase der Kompilierung sein oder ein Fehler ImpossibleError, der auf einen Compiler-Fehler hinweist.
Bei jedem dieser Fehlertypen wird versucht, so lange wie möglich Informationen für hübsches Drucken oder andere Analysen zu speichern. Noch wichtiger ist, dass ich durch das Fehlen eines Strings testen kann, dass das Ausführen eines falsch geschriebenen Programms durch die Typprüfung tatsächlich einen Vereinigungsfehler erzeugt! Sobald etwas a ist String, ist es für immer verschwunden und alle darin enthaltenen Informationen sind für den Compiler / die Tests undurchsichtig, daher Either Stringist es auch nicht großartig.
Schließlich packe ich diesen Typ in ExceptTeinen neuen Monadentransformator von MTL. Dies ist im Wesentlichen EitherTund kommt mit einer schönen Reihe von Funktionen zum Werfen und Auffangen von Fehlern auf eine reine, angenehme Art und Weise.
Schließlich ist zu erwähnen, dass Haskell über die Mechanismen verfügt, mit denen Ausnahmen wie in anderen Sprachen behandelt werden können IO. Ich weiß, dass manche Leute diese gern für IOschwere Anwendungen verwenden, bei denen möglicherweise alles versagt, aber so selten, dass sie nicht gerne darüber nachdenken. Ob Sie diese unreinen Ausnahmen verwenden oder einfach nur, ExceptT Error IOist Geschmackssache. Ich persönlich entscheide mich dafür, ExceptTweil ich gerne an die Möglichkeit eines Scheiterns erinnert werde.
Zusammenfassend
Maybe - Ich kann auf eine offensichtliche Weise scheitern
Either CustomType - Ich kann scheitern, und ich sage Ihnen, was passiert ist
IO+ Ausnahmen - Ich scheitere manchmal. Überprüfen Sie meine Dokumente, um zu sehen, was ich bei der Arbeit werfe
error - Ich hasse dich auch User
headoderlastso gut zu sein scheinen.errorIch habe mich gefragt, ob das wirklich eine gute Möglichkeit ist, Dinge zu tun, und ich habe einfach etwas verpasst. Dies beantwortet diese Frage. :)