Computação assíncrona com validação em Scala usando Scalaz

Estando escrevendo uma biblioteca completamente assíncrona para acessar um serviço remoto (usando o Play2.0), estou usandoPromise eValidation para criar uma chamada sem bloqueio, que tem um tipo apresentando falha e resultado válido de uma só vez.

Promise vem da Play2-scala, ondeValidation vem de scalaz.

Então, aqui está o tipo de exemplos de tais funções

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

Até agora, tudo bem, agora se eu quiser compô-los, posso usar o fato de quePromise apresentar umflatMap, então eu posso fazer isso para uma compreensão

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

Ok, eu peguei um atalho para o meu problema aqui porque eu não reutilizei oValidation resultados dentro da compreensão. Então, se eu quiser reutilizarx emgaqui está como eu poderia fazer

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

É justo, mas esse tipo de clichê vai poluir meu código repetidas vezes. O problema aqui é que eu tenho uma espécie de estrutura monádica de dois níveis comoM[N[_]].

Neste estágio, existe alguma estrutura na programação que permita trabalhar com essa estrutura pulando facilmente o nível secongo:

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

Agora, abaixo é como eu consegui algo semelhante.

Eu criei uma espécie de estrutura monádica que envolve os dois níveis em um, vamos dizerValidationPromised que polvilhou oPromise digite com dois métodos:

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

Isso me permite fazer essas coisas

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

Como podemos ver/~~> é bem parecido comflatMap mas pula um nível. O problema é a verbosidade (é por isso que "para compreensão" existe em Scala e "fazer" em Haskell).

Outro ponto, eu tenho o/~> que fica como ummap também, mas funciona no segundo nível (em vez do tipo válido -terceiro nível)

Então, minha segunda pergunta é corolária para a primeira ... Estou estudando uma solução sustentável com essa construção?

desculpe por tanto tempo

questionAnswers(1)

yourAnswerToTheQuestion