首页 文章

Scala从Try到Future的隐式转换

提问于
浏览
2

我正在尝试将 TryFuture s混合在Scala的 for 循环中,而没有使用 Future.fromTry 明确地将 Try 转换为 Future . 看起来它在某些情况下会自动运行,但在其他情况下则不然 .

以下代码段失败了

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

for {
  a <- Try(5)
  b <- Future(10)
} yield { a + b }

类型不匹配; found:scala.concurrent.Future [Int] required:scala.util.Try [?] b < - Future {10} ^编译失败

另一方面,如果我删除关键字 yield ,它的工作原理是:

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

for {
  a <- Try(5)
  b <- Future(10)
} { println(a + b) }

当我将 for 循环重写为嵌套的 foreachmap 时,它也有效:

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

有人可以解释我为什么会这样吗?这是一个错误吗?或者我错过了什么?

PS . 它与Scala 2.11和2.12中的行为相同 .

1 回答

  • 3

    foreach 返回 Unit 类型;因此"common"类型 .

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

    Try(5).foreach(a => Future(10).foreach(b => println(a + b)))
    

    你可以处理 FutureTry (两个不同的monad),只要你将它们链接在 foreach 周围 .

    如果添加 yield 关键字,编译器将使用 flatMap / map 解释您的for-understandnce;如下:

    Try(5).flatMap(a => Future(10).map(b => a + b))
    

    Try#flatMap 期望一个函数具有 Try 作为返回类型,但它得到一个 Future ,使整个不编译 .

    TL;DR: foreach does not expect matching of function types during chaining since it returns Unit in all cases; that's why it compiles.

    请注意以下内容:

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

    因为 map 不需要压扁类型;所以用不同的"effects"包装编译 . 扁平化不同类型会使编译器失败;正如 flatMap 试图做的那样 .

相关问题