7

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

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

所以这里是此类函数的示例类型

  • F ::A => Promise[Validation[E, B]]
  • G ::B => Promise[Validation[E, C]]

到目前为止,很好,现在如果我想编写它们,我可以简单地使用Promise呈现 a的事实flatMap,所以我可以用一个理解来完成

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

好的,我在这里解决了我的问题,因为我没有Validation在理解范围内重用结果。所以如果我想重用xin g,我可以这样做

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

很公平,但是这种样板会一遍又一遍地污染我的代码。这里的问题是我有一种像M[N[_]].

在这个阶段,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但在第二级(而不是 Valid 类型 -第三级)

所以我的第二个问题是前一个问题的推论......我是否正在通过这种结构来实现可持续的解决方案?

抱歉这么久

4

1 回答 1

4

您在这里寻找的概念是monad 转换器。简而言之,monad 转换器通过允许您“堆叠”它们来补偿不组成的 monad。

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

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

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

于 2012-06-10T16:09:21.343 回答