Wie kann ich den Fluss von Option Monad umkehren?

8

sagen, ich habe eine Reihe von "Validierung" -Funktionen, die keine zurückgeben, wenn es keinen Fehler gibt, andernfalls gibt es Some (String) zurück, die die Fehlermeldung angeben. Etwas wie das Folgende ...

%Vor%

Ich werde sie in einer Sequenz aufrufen und sobald man Some (String) zurückgibt, halte ich an und gebe dasselbe zurück. Wenn None zurückgegeben wird, gehe ich zum nächsten, bis die Sequenz beendet ist. Wenn alle keine zurückgeben, gebe ich keine zurück.

Ich möchte sie in einem "zum Ausdruck bringen" zusammenkleben. Etwas wie ...

%Vor%

Allerdings fließt Option genau das Gegenteil, was ich hier möchte. Es stoppt bei None und folgt mit Some (String).

Wie kann ich so etwas erreichen?

    
sanjib 15.11.2010, 12:07
quelle

4 Antworten

17

Sie können die Aufrufe einfach mit der Methode orElse unter Option

verketten %Vor%

oder Sie könnten eine Reihe von Validierungsmethoden ausführen, die in Funktionen konvertiert wurden

%Vor%     
Don Mackenzie 15.11.2010 13:19
quelle
3

Die scalaz Bibliothek hat einen Typ namens Validation , der eine unglaubliche Gymnastik mit Fehlern und Erfolg ermöglicht. Angenommen, Sie haben einige Methoden, die entweder eine Fehlermeldung Fehler oder ein erfolgreiches Ergebnis (A / B / C) zurückgeben können:

%Vor%

Diese können zusammen mit dem anwendungsspezifischen Funktor verwendet werden, um die Aufrufe zu verketten:

%Vor%

Beachten Sie, dass bei einem Fehler von foo1/2/3 die gesamte Komposition mit einer nicht leeren Liste (NEL) von Fehlernachrichten fehlschlägt. Wenn mehrere Fehler auftreten, erhalten Sie alle Fehlermeldungen.

Es ist eine Killer-App. Beispiele, wie ein Erfolg und ein Fehler wie folgt zurückgegeben werden, sind

%Vor%     
oxbow_lakes 16.11.2010 10:12
quelle
2

Können Sie nicht einfach die Iteratoren kombinieren und dann das erste Element nehmen? Etwas wie:

%Vor%     
Steve 15.11.2010 12:54
quelle
0

Ich denke, Sie könnten von der Verwendung von Lift Box profitieren, die Full (dh Some ), Empty (dh None ) und Failure (ein Empty mit einem Grund, warum es leer ist und das verkettet werden kann). David Pollak hat einen guten Blogbeitrag , in dem er vorgestellt wird. Kurz gesagt, Sie könnten so etwas tun (nicht getestet):

%Vor%

Dies ist nicht kürzer als das ursprüngliche Beispiel, aber es ist meiner Meinung nach etwas logischer, mit dem Ergebnis einer erfolgreichen Validierung in Full und einer fehlgeschlagenen Validierung in Failure .

Allerdings können wir kleiner werden. Erstens, da unsere Validierungsfunktion Box[String] zurückgibt, können sie Failure s selbst zurückgeben, und wir müssen Empty nicht in Failure selbst umwandeln:

%Vor%

Aber Box hat auch eine or -Methode, die dasselbe Box zurückgibt, wenn es Full ist, oder das andere Box , wenn dies nicht der Fall ist. Das würde uns geben:

val validation = validate1 oder validate2 oder validate3

Diese Zeile stoppt jedoch bei der ersten Validierung Erfolg , nicht beim ersten Fehler. Es könnte Sinn machen, eine andere Methode zu machen, die das tut, was Sie wollen (vielleicht unless ?), Obwohl ich nicht sagen kann, dass es wirklich viel nützlicher wäre als der Ansatz zum Verständnis.

Aber hier ist eine kleine Bibliothek, die das macht:

%Vor%

Dies ist ein schneller Hack, der auf meinem begrenzten Verständnis des Scala-Typsystems basiert, wie Sie in folgendem Fehler sehen können:

%Vor%

Allerdings sollte das ausreichen, um Sie auf den richtigen Weg zu bringen.

Natürlich haben die Lift ScalaDocs weitere Informationen zu Box .

    
pr1001 15.11.2010 14:10
quelle

Tags und Links