首页
学习
活动
专区
圈层
工具
发布
社区首页 >问答首页 >在for-comprehension中使用List的组合选项会根据顺序导致类型不匹配

在for-comprehension中使用List的组合选项会根据顺序导致类型不匹配
EN

Stack Overflow用户
提问于 2011-01-18 09:09:53
回答 3查看 21.9K关注 0票数 83

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

代码语言:javascript
复制
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)

如果我将其中的一些与列表进行交换,它编译得很好:

代码语言:javascript
复制
for (first <- List(1,2,3); second <- Some(1)) yield (first,second)
res41: List[(Int, Int)] = List((1,1), (2,1), (3,1))

这也可以很好地工作:

代码语言:javascript
复制
for (first <- Some(1); second <- Some(2)) yield (first,second)
EN

回答 3

Stack Overflow用户

回答已采纳

发布于 2011-01-18 09:38:26

For理解被转换为对mapflatMap方法的调用。例如这一条:

代码语言:javascript
复制
for(x <- List(1) ; y <- List(1,2,3)) yield (x,y)

变成这样:

代码语言:javascript
复制
List(1).flatMap(x => List(1,2,3).map(y => (x,y)))

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

现在,让我们来看看flatMap是如何在Option中声明的

代码语言:javascript
复制
def flatMap [B] (f: (A) ⇒ Option[B]) : Option[B]

请记住这一点。让我们来看一下erroneous for converted (带有Some(1)的那个)是如何转换为一系列map调用的:

代码语言:javascript
复制
Some(1).flatMap(x => List(1,2,3).map(y => (x, y)))

现在,很容易看出,flatMap调用的参数是返回List的参数,而不是所需的Option

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

代码语言:javascript
复制
for(x <- Some(1).toSeq ; y <- List(1,2,3)) yield (x, y)

这样编译就很好了。值得注意的是,正如人们通常认为的那样,Option不是Seq的子类型。

票数 119
EN

Stack Overflow用户

发布于 2011-01-18 09:41:53

这可能与Option不是Iterable有关。隐式Option.option2Iterable将处理编译器期望second为Iterable的情况。我期望根据循环变量的类型,编译器的魔力是不同的。

票数 4
EN

Stack Overflow用户

发布于 2018-06-19 06:34:56

我一直觉得这很有帮助:

代码语言:javascript
复制
scala> val foo: Option[Seq[Int]] = Some(Seq(1, 2, 3, 4, 5))
foo: Option[Seq[Int]] = Some(List(1, 2, 3, 4, 5))

scala> foo.flatten
<console>:13: error: Cannot prove that Seq[Int] <:< Option[B].
   foo.flatten
       ^

scala> val bar: Seq[Seq[Int]] = Seq(Seq(1, 2, 3, 4, 5))
bar: Seq[Seq[Int]] = List(List(1, 2, 3, 4, 5))

scala> bar.flatten
res1: Seq[Int] = List(1, 2, 3, 4, 5)

scala> foo.toSeq.flatten
res2: Seq[Int] = List(1, 2, 3, 4, 5)
票数 1
EN
页面原文内容由Stack Overflow提供。腾讯云小微IT领域专用引擎提供翻译支持
原文链接:

https://stackoverflow.com/questions/4719592

复制
相关文章

相似问题

领券
问题归档专栏文章快讯文章归档关键词归档开发者手册归档开发者手册 Section 归档