在编写一个完全异步的库来访问远程服务(使用 Play2.0)时,我正在使用Promise
并Validation
创建非阻塞调用,该调用具有一次显示失败和有效结果的类型。
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
在理解范围内重用结果。所以如果我想重用x
in 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 类型 -第三级)
所以我的第二个问题是前一个问题的推论......我是否正在通过这种结构来实现可持续的解决方案?
抱歉这么久