【问题标题】:Scala for-comprehension type inferenceScala 用于理解类型推断
【发布时间】:2013-05-24 23:54:41
【问题描述】:
下一个代码
def f(chars: List[Char]): List[List[Char]] = chars match {
case Nil => List(Nil)
case x :: xs => for {
v <- f(xs)
} yield List(x) :: v
}
给出错误信息
- type mismatch; found : List[List[Any]] required: List[List[Char]]
请帮助我理解为什么“for”在这里选择最通用的 Any 而不是 Char?我应该阅读语言规范中的哪些主题?谢谢。
【问题讨论】:
标签:
scala
for-comprehension
【解决方案1】:
结果,你是yielding 是List[List[List[Char]]] 和List[List[Char]] 的混合体。 Scala 将其向上转换为 List[List[Any]]。对于您的情况,以下任何一项都可以完成这项工作:
scala> def f(chars: List[Char]): List[List[Char]] = chars match {
| case Nil => List(Nil)
| case x :: xs => for {
| v <- f(xs)
| } yield x :: v
| }
f: (chars: List[Char])List[List[Char]]
scala> def f(chars: List[Char]): List[List[Char]] = chars match {
| case Nil => List(Nil)
| case x :: xs => for {
| v <- f(xs)
| } yield List(x) ++ v
| }
f: (chars: List[Char])List[List[Char]]
【解决方案2】:
问题是List(x) -- 它必须是x。
首先,v 迭代f(xs) 的结果,f 返回List[List[Char]]。这意味着结果将是List[X],其中X 是yield 返回的类型。
v 的类型是List[Char],因为它正在迭代f(xs) 的内容。所以我们必须弄清楚List(x) :: v 的类型,它在List[Char] 上添加List[Char]。 not 将它们连接起来:它是将列表添加到仅包含字符的列表中。结果列表将同时包含Char 和List[Char]。
由于唯一同时满足两者的类型是Any,那么X 将是Any 和理解的结果List[Any]。