2016-04-21 7 views

Antwort

1

Per Konvention wird Either verwendet, um ein Ausnahmesystem zu emulieren, aber dafür ist es nicht ausgelegt.

Deshalb verwenden wir ErrorT für größere Implementierungen, da es mit dem Typ Error kommt, mit dem der Benutzer allgemeinere Ausnahmen definieren kann.

Sobald Sie jedoch mit der runErrorT die monadische Aktion des Typs ErrorT e Identity a ausgeführt haben, erhalten Sie einen Wert vom Typ Either e a. Also, diese Typen sind etwas äquivalent, nur dass ErrorT können Sie Funktionen wie throwError und catchError anstelle von either verwenden, die weniger klar ist (vor allem wenn sie wiederholt verwendet wird).

PS: Wie die Dokumentation angibt, ist Control.Monad.Error veraltet, Control.Monad.Except stattdessen.

+1

'fail' wird auch anders zwischen ihnen implementiert. –

+0

Danke, habe das nicht bemerkt. Ich bevorzuge es jedoch, 'fail' nicht zu verwenden, weil es den Fehler als' String' einschränkt. Es funktioniert für den Fall von OP, aber ich empfehle es nicht. – baxbaxwalanuksiwe

3

(Um dies zu vereinfachen, werde ich statt the deprecated ErrorT in Bezug auf die ExceptT Art beantworten. Meine Antwort für ErrorT nicht ganz richtig ist, aber es ist wahr Modulo einiger lästigen Tatsachen, die zur Abwertung von ErrorT geführt.)

Das Schlüsselkonzept hier zu verstehen ist isomorphism. Um es sehr informell zu formulieren, sind zwei Arten isomorph, wenn sie, obwohl sie oberflächlich verschieden sind, "im Wesentlichen das gleiche" sind. isomorph zwei Haskell-Typen sind, wenn beide können durch ein Paar von inversen Funktionen in einem „lossless“ Art und Weise in die andere umgewandelt werden:

Wir können durch das Hinzufügen dieses Konzept auf diesem Begriff ein bisschen mehr Fleisch setzen. In diesem Fall Either e a und EitherT e Identity a sind isomorph, da die folgenden zwei Funktionen Umkehrungen sind:

toEither :: ExceptT e Identity a -> Either e a 
toEither ma = runIdentity (runExceptT ma) 

toExceptT :: Either e a -> ExceptT e Identity a 
toExceptT (Left e) = throwError e 
toExceptT (Right a) = return a 

So oben durch die informellen Bemerkungen gehen, was das sagt, ist, dass die beiden Typen sind „im Wesentlichen gleich.“ Und das Fleisch, das die inversen Funktionen dieses Add ist, dass sie beweisen, dass:

  1. Wenn Sie irgendein Stück Code haben, der beiden Typen verwendet, Sie Refactoring können es die andere zu verwenden, und der Code wird produzieren genau die gleiche Ergebnisse und Verhalten;
  2. Wenn Sie zwei separate Bibliotheken haben, verwendet eine von ihnen die erste Art und die andere die zweite, Sie können sie überbrücken, indem Sie die Isomorphie-Funktionen verwenden und alles wird gut.

Also, was darauf ankommt, ist, dass oft viele verschiedene Möglichkeiten in der Programmierung gibt es genau das Gleiche zu tun. In diesem Fall ist ExceptT eine allgemeinere Version von Either, aber wenn Sie Identity als die Basismonade anschließen, erhalten Sie etwas, das genau das selbe arbeitet, das tut.Wir bevorzugen im Allgemeinen Either in diesem Fall, weil wir dann nicht so viel Standard haben, aber manchmal finden wir uns in einer Situation, wo wir ExceptT e Identity a bekommen und dann über den Isomorphismus zu wissen, dass es nicht wesentlich anders ist als Either e a.


Hier ist eine andere Möglichkeit, dies zu analysieren. Der ExceptT Typ wird wie folgt definiert:

newtype ExceptT e m a = ExceptT { runExceptT :: m (Either e a) } 

In Haskell, eine newtype Definition ist ein Isomorphismus (der ExceptT Konstruktor und die runExceptT Funktion sind Umkehrungen), was in diesem Fall bedeutet, dass die folgenden zwei Typen sind isomorph:

ExceptT e m a ~ m (Either e a) 

was bedeutet, dass diese beiden isomorph sind auch:

ExceptT e Identity a ~ Identity (Either e a) 

Aber 012.wird auch als newtype definiert:

newtype Identity a = Identity { runIdentity :: a } 

was bedeutet, dass dieser Isomorphismus auch gilt:

Identity a ~ a 

Und deshalb so tut dies hier:

Identity (Either e a) ~ Either e a 
ExceptT e Identity a ~ Either e a 

Wenn also eine Bibliothek transparent definiert einen Typ als newtype, es lohnt sich, diese Tatsache zu beachten. (Und das ist, warum Bibliothek Dokumentation in Haskell sagt Ihnen, ob ein Datentyp mit exportierten Konstrukteuren ist ein data oder eine newtype Definition-zu wissen, dass es ein newtype ist eine große Sache.)


Ein weiterer Vorteil bei dieser Suche in Begriffe von Isomorphismen sind, dass es Ihnen oft hilft, viele Standard-Haskell-Bibliotheken besser zu verstehen. Wie ich oben sagte, durch die newtype Definition von ExceptT, die folgenden Isomorphismus

ExceptT e m a ~ m (Either e a) 

hält Wenn es mit einem monadischen Typ des Formulars m a, arbeiten wir nennen in der Regel m die „Monade“ und a die „Ergebnistyp“. Betrachtet man es durch diese Linse, dann:

  1. In m (Either e a), m die Monade ist und Either e a ist der Ergebnistyp;
  2. In ExceptT e m a, ExceptT e m ist die Monade und a ist der Ergebnistyp.

So ist der ExceptT Monade Transformator ist ein Isomorphismus, die uns m (Either e a) so zu „drehen Sie die Perspektive“ auf Berechnungen des Typs ermöglicht es, dass wir a als Ergebnistyp statt Either e a behandeln. Es tut dies, indem es die Bedeutung der Monaden-Operationen von dem, was sie in m bedeuten, zu etwas ändert, das für den fraglichen "Perspektiv-Flip" verantwortlich ist.