使用Scalaz在Scala中验证异步计算

正在编写一个完全异步库来访问远程服务(使用Play2.0)时,我使用PromiseValidation来创建非阻塞呼叫,该呼叫具有一种呈现失败和有效结果的类型。

Promise来自Play2-scala,其中Validation来自scalaz。

所以这里就是这种功能的例子

  • f :: A => Promise[Validation[E, B]]
  • g :: B => Promise[Validation[E, C]]
  • 到目前为止,如此好,现在如果我想编写它们,我可以简单地使用Promise呈现flatMap这一事实,所以我可以用一个理解

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

    好的,我在这里采取了一个快捷方式来解决我的问题,因为我没有在重新使用for-comprehension中的Validation结果。 所以如果我想在g重用x ,这里就是我可以做到的

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

    很公平,但这种样板会反复污染我的代码。 这里的问题是我有一种像M[N[_]]这样的二级Monadic结构。

    在这个阶段,f°编程中是否有任何结构可以通过轻松跳过secong级别来处理这种结构:

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

    现在,下面是我如何取得类似的成就。

    我创建了一种Monadic结构,将两个层次包装在一起,比方说ValidationPromised ,它用两种方法来呈现Promise类型:

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

    这允许我做这样的事情

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

    我们可以看到/~~>flatMap非常相似,但跳过了一个级别。 问题在于冗长(这就是为什么Scala中存在“for-comprehension”,Haskell中是“do”)。

    还有一点,我认为/~>也像map一样,但是在第二层次上工作(而不是有效类型 - 第三层次)

    所以我的第二个问题是前者的必然结果......我是否正在采用这种结构来实现可持续解决方案?

    很抱歉,那么久


    你在这里寻找的概念是monad变形金刚。 简而言之,monad变压器通过补偿monad而不是让你“叠加”它们。

    你没有提到你正在使用的Scalaz版本,但是如果你看看Scalaz-7分支,你会发现ValidationT。 这可用于将任何F[Validation[E, A]]包装到ValidationT[F, E, A] ,其中您的情况为F = Promise 。 如果您更改fg以返回ValidationT ,那么您可以将代码保留为

    for {
      x ← f(a)
      y ← g(b)
    } yield y
    

    这会给你一个ValidationT[Promise, E, B]

    链接地址: http://www.djcxy.com/p/60329.html

    上一篇: Async computation with Validation in Scala using Scalaz

    下一篇: Warn on calls to UIKit from background threads