Scala从Try到Future的隐式转换

Scala从Try到Future的隐式转换,scala,for-loop,future,implicit-conversion,implicit,Scala,For Loop,Future,Implicit Conversion,Implicit,我试图在Scala中的for循环中将Trys与Futures混合,而不显式地将Trys转换为Futures与Future.fromTry。看起来它在某些情况下会自动工作,但在其他情况下不会 以下代码段在以下情况下失败: import scala.concurrent.ExecutionContext.Implicits.global import scala.concurrent._ import scala.util._ for { a <- Try(5) b <- Fu

我试图在Scala中的
for
循环中将
Try
s与
Future
s混合,而不显式地将
Try
s转换为
Future
s与
Future.fromTry
。看起来它在某些情况下会自动工作,但在其他情况下不会

以下代码段在以下情况下失败:

import scala.concurrent.ExecutionContext.Implicits.global
import scala.concurrent._
import scala.util._

for {
  a <- Try(5)
  b <- Future(10)
} yield { a + b } 
当我将
for
循环重写为嵌套的
foreach
map
时,它也会起作用:

@ Try(5) foreach { a => Future(10) foreach { b => println(a + b) } }
15


@ Try(5) map { a => Future(10) map { b => a + b } }
res5: Try[Future[Int]] = Success(Future(Success(15)))
有人能解释一下为什么会这样吗?这是虫子吗?还是我遗漏了什么


注:Scala 2.11和2.12中的行为相同。

foreach
返回一个
单元
类型;因此是一种“普通”类型

如果没有
yield
关键字,编译器会将您的理解解释为:

Try(5).foreach(a => Future(10).foreach(b => println(a + b)))
您可以处理
未来
尝试
(两个不同的单子),只要您将它们链接到
foreach

如果您添加
yield
关键字,编译器将使用
flatMap
/
map
对您进行解释以供理解;详情如下:

Try(5).flatMap(a => Future(10).map(b => a + b))
Try#flatMap
需要一个返回类型为
Try
的函数,但它得到了一个
Future
,使得整个函数不可编译

TL;DR:
foreach
不希望在链接期间匹配函数类型,因为它在所有情况下都返回单元;这就是它编译的原因。

请注意:

Try(5) map { a => Future(10) map { b => a + b } }
因为
map
不需要展平类型,所以可以工作;因此,包装会产生不同的“效果”。 展平不同类型会导致编译器失败;正如
flatMap
尝试做的那样

Try(5) map { a => Future(10) map { b => a + b } }