旧版本的API看起来像这样(感谢@travisbrown建议traverseU
解决方案here)。请注意,这两个API是作为玩具示例创建的,用于说明此SO问题的要点。真正的代码正在做更多有趣的事情。
def anotherFunc: Throwable \/ List[String] = personList.flatMap { pl =>
pl.traverseU { p =>
for {
s <- Option("fakeString").\/>(new Throwable("not found"))
} yield s
}
}
其中
case class Person(name: String)
private def personList: \/[Throwable, List[Person]] = {
\/.fromTryCatch {
List(Person("John"))
}
}
现在将此def
转换为基于Future
的内容将如下所示
def anotherFunc: Future[Throwable \/ List[String]] = Future {
personList.flatMap { pl =>
pl.traverseU { p =>
for {
s <- Option("fakeString").\/>(new Throwable("not found"))
} yield s
}
}
}
现在如前所述,这是一个玩具示例,但我在for
理解中有一个或多个生成器,它返回包含在Future
中的析取,例如Future[\/[Throwable,String]]
你可以想象下面的s1
for {
s <- Option("fakeString").\/>(new Throwable("not found"))
//s1 <- Future{"returning Future[\/[Throwable,String]" }
} yield //value out of s1 future must be yielded
这里需要monad变换吗?
e.g。要获得out Future
monad(在这种情况下为s1
)并转换为
适当地匹配anotherFunc
的回报?不确定EitherT
是否可以提供帮助?
更新
简化示例。这是其中一个生成器返回anotherFunc
时Future[\/[Throwable,String]]
的样子。基本上要避免使用Await
def anotherFunc: Future[Throwable \/ List[String]] = Future {
personList.flatMap { pl =>
pl.traverseU { p =>
for {
s <- Option("fakeString").\/>(new Throwable("not found"))
f <- Await.result(futureResult, 1.seconds)
} yield f
}
}
}
def futureResult = Future{Option("""another Disjunction is called here - which returns a Future[\/[Throwable,T]""").\/>(new Throwable("not found"))}