Asynchrone Berechnung mit Validierung in Scala mit Scalaz

Ich schreibe gerade eine vollständig asynchrone Bibliothek, um auf einen Remote-Dienst zuzugreifen (mit Play2.0)Promise undValidation um einen nicht blockierenden Anruf zu erstellen, der einen Fehlertyp und ein gültiges Ergebnis auf einmal aufweist.

Promise kommt von Play2-Scala, woValidation kommt von scalaz.

Hier ist die Art von Beispielen für solche Funktionen

f ::A => Promise[Validation[E, B]]g ::B => Promise[Validation[E, C]]

So weit, so gut, jetzt, wenn ich sie komponieren möchte, kann ich einfach die Tatsache nutzen, dassPromise präsentieren aflatMap, damit ich es mit einem for-verständnis machen kann

for (
   x <- f(a);
   y <- g(b)
) yield y

Ok, ich habe hier eine Abkürzung zu meinem Problem genommen, weil ich die nicht wiederverwendet habeValidation Ergebnisse im Rahmen des Vorverständnisses. Also wenn ich wiederverwenden willx imgHier ist, wie ich tun könnte

for (
   x <- f(a); // x is a Validation
   y <- x.fold(
      fail => Promise.pure(x),
      ok => g(ok)
   )
) yield y

Fair genug, aber diese Art von Boilerplate wird meinen Code immer und immer wieder verschmutzen. Das Problem dabei ist, dass ich eine Art zweistufige monadische Struktur habeM[N[_]].

In dieser Phase gibt es eine Struktur in der f ° -Programmierung, die es ermöglicht, mit einer solchen Struktur zu arbeiten, indem die zweite Ebene leicht übersprungen wird:

for (
   x <- f(a); //x is a B
   y <- g(b) 
) yield y

Im Folgenden erfahren Sie, wie ich etwas Ähnliches erreicht habe.

Ich habe eine Art monadische Struktur geschaffen, die die beiden Ebenen in einer zusammenfasstValidationPromised die pimpte diePromise Schreibe mit zwei Methoden:

def /~> [EE >: E, B](f: Validation[E, A] => ValidationPromised[EE, B]): ValidationPromised[EE, B] = 
    promised flatMap { valid => 
        f(valid).promised
    }

def /~~>[EE >: E, B](f: A => ValidationPromised[EE, B]): ValidationPromised[EE, B] = 
    promised flatMap { valid => 
        valid.fold (
            bad => Promise.pure(KO(bad)),
            good => f(good).promised
        )
    }

Dies ermöglicht mir, solche Dinge zu tun

      endPoint.service /~~>                                   //get the service
      (svc =>                                                 //the service
        svc.start /~~> (st =>                                 //get the starting elt
          svc.create(None) /~~>                               //svc creates a new elt
          (newE =>                                            //the created one
            newEntry.link(st, newE) /~~>                      //link start and the new
            (lnk => Promise.pure(OK((st, lnk, newE))))        //returns a triple => hackish 
          ) 
        )
      )

Wie wir sehen können/~~> ist ziemlich ähnlich zuflatMap überspringt aber eine Ebene. Das Problem ist die Ausführlichkeit (deshalb gibt es in Scala "zum Verständnis" und in Haskell "zu tun").

Ein weiterer Punkt, ich habe die/~> das steht wie einmap funktioniert aber auch auf der zweiten Ebene (anstelle des gültigen Typs -dritte Niveau)

Meine zweite Frage ist also eine Folge der ersteren ... Nähere ich mich mit dieser Konstruktion einer nachhaltigen Lösung?

Es tut mir leid, so lange zu sein

Antworten auf die Frage(1)

Ihre Antwort auf die Frage