scala - 在 for 理解中将选项与列表组合会导致类型不匹配,具体取决于顺序

标签 scala for-loop type-mismatch for-comprehension scala-option

为什么这种构造会导致 Scala 中出现类型不匹配错误?

for (first <- Some(1); second <- List(1,2,3)) yield (first,second)

<console>:6: error: type mismatch;
 found   : List[(Int, Int)]
 required: Option[?]
       for (first <- Some(1); second <- List(1,2,3)) yield (first,second)

如果我将 Some 与 List 进行切换,它可以正常编译:

for (first <- List(1,2,3); second <- Some(1)) yield (first,second)
res41: List[(Int, Int)] = List((1,1), (2,1), (3,1))

这也可以正常工作:

for (first <- Some(1); second <- Some(2)) yield (first,second)

最佳答案

For 推导式会转换为对 mapflatMap 方法的调用。例如这个:

for(x <- List(1) ; y <- List(1,2,3)) yield (x,y)

变成:

List(1).flatMap(x => List(1,2,3).map(y => (x,y)))

因此,第一个循环值(在本例中为 List(1))将接收 flatMap 方法调用。由于 List 上的 flatMap 返回另一个 List,因此 for 理解的结果当然是一个 List。 (这对我来说是新的:因为理解并不总是产生流,甚至不一定产生 Seqs。)

现在,看看Option中如何声明flatMap:

def flatMap [B] (f: (A) ⇒ Option[B]) : Option[B]

请记住这一点。让我们看看错误的理解(带有 Some(1) 的错误)如何转换为一系列映射调用:

Some(1).flatMap(x => List(1,2,3).map(y => (x, y)))

现在,很容易看出 flatMap 调用的参数返回 List,而不是 Option,如下所示必填。

为了解决这个问题,您可以执行以下操作:

for(x <- Some(1).toSeq ; y <- List(1,2,3)) yield (x, y)

编译得很好。值得注意的是,Option 并不是通常假设的 Seq 的子类型。

关于scala - 在 for 理解中将选项与列表组合会导致类型不匹配,具体取决于顺序,我们在Stack Overflow上找到一个类似的问题: https://stackoverflow.com/questions/4719592/

相关文章:

vba - 在 for 循环中键入不匹配,包括对工作表单元格值的测试

scala - 嵌套表达式

json - 单个字段类的 Scala json 解析

scala - 如何将List中的两个连续元素转换为Map中的条目?

javascript - Forloop困惑

javascript - 获取唯一值和重复值

haskell - 创建一个矩形? - haskell

scala - 如何不让 Gradle 立即退出 Scala 的 REPL?

ios - Swift 3 循环 JSON 数据

java - 类型不匹配,无法从 void 转换为 char[]