Kann jemand Unterschied zwischenDifferenz zwischen zwei Monaden: ErrorT e Identität v und entweder e v
ErrorT String Identity Integer
und Either String Integer
erklären?
Kann jemand Unterschied zwischenDifferenz zwischen zwei Monaden: ErrorT e Identität v und entweder e v
ErrorT String Identity Integer
und Either String Integer
erklären?
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.
'fail' wird auch anders zwischen ihnen implementiert. –
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
(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:
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:
m (Either e a)
, m
die Monade ist und Either e a
ist der Ergebnistyp;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.
Was lässt dich denken, dass es einen gibt? Sie sind im Wesentlichen die gleichen bis zu einigen Neueinführungen. –