Obliczenia asynchroniczne z walidacją w Scali przy użyciu Scalaz

Pisząc całkowicie asynchroniczną bibliotekę, aby uzyskać dostęp do usługi zdalnej (używając Play2.0), używamPromise iValidation aby utworzyć połączenie niezablokowane, które ma typ prezentujący niepowodzenie i poprawny wynik na raz.

Promise pochodzi z Play2-scala, gdzieValidation pochodzi ze skalazu.

Oto rodzaj przykładów takich funkcji

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

Jak dotąd, tak dobrze, teraz, jeśli chcę je skomponować, mogę to w prosty sposób wykorzystaćPromise przedstawić aflatMap, więc mogę to zrobić ze zrozumieniem

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

Ok, zabrałem tutaj skrót do mojego problemu, ponieważ nie użyłem go ponownieValidation wyniki w ramach for-comprehension. Więc jeśli chcę ponownie użyćx wg, oto jak mogę to zrobić

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

Wystarczająco dobrze, ale ten rodzaj kotła będzie w dalszym ciągu zanieczyszczać mój kod. Problem polega na tym, że mam rodzaj dwupoziomowej struktury monadycznejM[N[_]].

Czy na tym etapie istnieje jakakolwiek struktura programowania w ° F, która umożliwia pracę z taką strukturą przez łatwe pomijanie drugiego poziomu:

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

Poniżej, w jaki sposób osiągnąłem coś podobnego.

Stworzyłem rodzaj monadycznej struktury, która owija dwa poziomy w jeden, powiedzmyValidationPromised który zepsułPromise wpisz dwoma metodami:

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
        )
    }

To pozwala mi robić takie rzeczy

      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 
          ) 
        )
      )

Jak możemy zobaczyć/~~> jest bardzo podobny doflatMap ale pomija jeden poziom. Problemem jest gadatliwość (dlatego „for-comprehension” istnieje w Scali i „zrobić” w Haskell).

Kolejny punkt, mam/~> to jest jakmap działa również na drugim poziomie (zamiast typu Valid -trzeci poziom)

Więc moje drugie pytanie jest następstwem tego pierwszego ... Czy przy tej konstrukcji popieram zrównoważone rozwiązanie?

przepraszam, że tak długo

questionAnswers(1)

yourAnswerToTheQuestion