types不匹配在斯卡拉理解
为什么这个构造在Scala中导致types不匹配错误?
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) 
	
 理解转换为对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 ,因此理解的结果当然是List 。  (这对我来说是新的:理解并不总是导致stream,甚至不一定在Seq s。) 
 现在,看看如何在Option声明flatMap : 
 def flatMap [B] (f: (A) ⇒ Option[B]) : Option[B] 
 记住这一点。 让我们来看看错误的理解(带有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那样是一个子types。 
一个简单的提示要记住, 理解将尝试返回第一个生成器的集合的types,在这种情况下选项[Int]。 所以,如果你从Some(1)开始,你应该期待Option [T]的结果。
如果你想得到一个Listtypes的结果,你应该从List生成器开始。
 为什么有这个限制,而不是假设你总是想要某种顺序? 你可以有一个有意义的Option 。 也许你有一个Option[Int] ,你想结合一些东西来得到一个Option[List[Int]] ,用下面的函数说: (i:Int) => if (i > 0) List.range(0, i) else None ; 当事情没有“有意义”的时候,你可以写下这个并得到None: 
 val f = (i:Int) => if (i > 0) Some(List.range(0, i)) else None for (i <- Some(5); j <- f(i)) yield j // returns: Option[List[Int]] = Some(List(0, 1, 2, 3, 4)) for (i <- None; j <- f(i)) yield j // returns: Option[List[Int]] = None for (i <- Some(-3); j <- f(i)) yield j // returns: Option[List[Int]] = None 
 如何在一般情况下扩大理解实际上是将M[T]types的对象与函数(T) => M[U]以获得(T) => M[U]types的对象的相当一般的机制。 在你的例子中,M可以是Option或者List。 一般来说它必须是M型。 所以你不能把Option和List结合起来。 对于可以是M的其他东西的例子,看看这个特质的子类 。 
 为什么在List[T]和(T) => Option[T]结合起来了呢? 在这种情况下,图书馆使用更通用的types。 所以你可以将List和Traversable结合起来,并且有一个从Option到Traversable的隐式转换。 
底线是这样的:想想你想要什么types的expression式返回,并以该types作为第一个生成器开始。 如有必要,将其包裹在该types中。
 这可能与Option不是可迭代的有关。 隐含的Option.option2Iterable将处理编译器期望第二个是可Option.option2Iterable的情况。 我期望编译器的魔术是不同的,取决于循环variables的types。