Fel*_*ura 77 for-loop scala 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)
Run Code Online (Sandbox Code Playgroud)
如果我用List切换Some,它编译得很好:
for (first <- List(1,2,3); second <- Some(1)) yield (first,second)
res41: List[(Int, Int)] = List((1,1), (2,1), (3,1))
Run Code Online (Sandbox Code Playgroud)
这也很好:
for (first <- Some(1); second <- Some(2)) yield (first,second)
Run Code Online (Sandbox Code Playgroud)
Mad*_*doc 114
用于推导被转换成呼叫到map
或flatMap
方法.例如这一个:
for(x <- List(1) ; y <- List(1,2,3)) yield (x,y)
Run Code Online (Sandbox Code Playgroud)
成为:
List(1).flatMap(x => List(1,2,3).map(y => (x,y)))
Run Code Online (Sandbox Code Playgroud)
因此,第一个循环值(在这种情况下,List(1)
)将接收flatMap
方法调用.因为flatMap
在List
返回另一个时List
,理解的结果当然是一个List
.(这对我来说是新的:因为理解并不总是导致流,甚至不一定是Seq
s.)
现在,看一下如何flatMap
声明Option
:
def flatMap [B] (f: (A) ? Option[B]) : Option[B]
Run Code Online (Sandbox Code Playgroud)
记住这一点.让我们看看理解错误(带有错误)如何Some(1)
转换为一系列地图调用:
Some(1).flatMap(x => List(1,2,3).map(y => (x, y)))
Run Code Online (Sandbox Code Playgroud)
现在,很容易看出flatMap
调用的参数是根据需要返回a List
而不是an的东西Option
.
为了解决问题,您可以执行以下操作:
for(x <- Some(1).toSeq ; y <- List(1,2,3)) yield (x, y)
Run Code Online (Sandbox Code Playgroud)
编译得很好.值得注意的是,这Option
不是Seq
通常假设的子类型.
huy*_*hjl 31
一个容易记住的提示,因为理解将尝试返回第一个生成器的集合的类型,在这种情况下为Option [Int].因此,如果从Some(1)开始,您应该期望Option [T]的结果.
如果需要List类型的结果,则应该从List生成器开始.
为什么有这个限制并且不假设你总是想要某种顺序?你可以有一个返回有意义的情况Option
.也许你有一个Option[Int]
你想要的东西结合起来,得到了Option[List[Int]]
,说有以下功能:(i:Int) => if (i > 0) List.range(0, i) else 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
Run Code Online (Sandbox Code Playgroud)
在一般情况下如何扩展理解实际上是一种相当普遍的机制,将类型的对象M[T]
与函数组合(T) => M[U]
以获得类型的对象M[U]
.在您的示例中,M可以是Option或List.一般来说,它必须是相同的类型M
.因此,您无法将Option与List结合使用.有关其他可能的示例M
,请查看此特征的子类.
为什么结合List[T]
使用(T) => Option[T]
,虽然工作的时候,你开始与列表?在这种情况下,库在有意义的地方使用更通用的类型.因此,您可以将List与Traversable结合使用,并且存在从Option到Traversable的隐式转换.
底线是:考虑您希望表达式返回的类型,并以该类型作为第一个生成器开始.如有必要,请将其包裹在该类型中.
归档时间: |
|
查看次数: |
19688 次 |
最近记录: |