为什么这种构造会在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)如果我将其中的一些与列表进行交换,它编译得很好:
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)发布于 2011-01-18 09:38:26
For理解被转换为对map或flatMap方法的调用。例如这一条:
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 comprehension的结果当然是一个List。(这对我来说是新的:因为理解并不总是产生流,甚至不一定产生Seq。)
现在,让我们来看看flatMap是如何在Option中声明的
def flatMap [B] (f: (A) ⇒ Option[B]) : Option[B]请记住这一点。让我们来看一下erroneous for converted (带有Some(1)的那个)是如何转换为一系列map调用的:
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的子类型。
发布于 2011-01-18 09:41:53
这可能与Option不是Iterable有关。隐式Option.option2Iterable将处理编译器期望second为Iterable的情况。我期望根据循环变量的类型,编译器的魔力是不同的。
发布于 2018-06-19 06:34:56
我一直觉得这很有帮助:
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)https://stackoverflow.com/questions/4719592
复制相似问题