类型必须在 for-compression 中对齐是什么意思?

What does it mean that the types have to align in for-comprensions?

当类型必须与 scala 对齐才能理解时,有人可以详细说明这意味着什么吗?

for {
..
..
}

如果看涨所有return期货就可以了? 只是想了解它何时有效,何时无效。

对于 map/flatMap 调用的理解脱糖,因此请考虑他们的签名。例如,考虑 Option#flatMap

def flatMap[B](f: (A) => Option[B]): Option[B]

我们看到 Option 继续参与其中。现在观察 since

for {
  a <- Some(41)
  b <- Some(1)
} yield a + b

变成

Some(41).flatMap(a => Some(1).map(b => a + b))

这意味着如果你试图在 for-comprehension 中混合 monadic 类型,例如

for {
  a <- Some(41)
  b <- Try(1)
} yield a + b

然后它会脱糖到

Some(41).flatMap(a => Try(1).map(b => a + b))
                       |
                  types do not align

但我们已经看到 Option#flatMap 期望 A => Option[B] 而不是 A => Try[B]

一个似乎可以打破规则的地方是将 Option 与 List 混合使用时

scala> for {
     |   a <- List(41)
     |   b <- Some(1)
     | } yield (a + b)
val res0: List[Int] = List(42)

但这是可行的,因为 List#flatMap 接受一个从 AIterableOnce 的函数,并且 Option 在 Scala 2.13IterableOnce 中被制作

def flatMap[B](f: A => IterableOnce[B])

请注意,反之亦然:

scala> for {
     |   a <- Some(41)
     |   b <- List(1)
     | } yield a + b
         b <- List(1)
           ^
On line 3: error: type mismatch;
        found   : List[Int]
        required: Option[?]

一般来说,给定一个有效的类型 F[A] 然后内部 for-comprehension F 不能变化,除非我们使用子类型,另一方面 A 确实可以变化。