Scala for-comprehension类型推断

时间:2013-05-10 14:40:21

标签: scala for-comprehension

下一个代码

  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?我应该阅读语言规范中的哪个主题?谢谢。

2 个答案:

答案 0 :(得分:10)

结果,您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]]

答案 1 :(得分:6)

问题是List(x) - 它必须是x

首先,v迭代f(xs)的结果,f返回List[List[Char]]。这意味着结果将为List[X],其中Xyield返回的类型。

v的类型为List[Char],因为它正在迭代f(xs)的内容。因此,我们必须确定List(x) :: v的类型,它在List[Char]上加List[Char]连接它们:它将列表添加到仅包含字符的列表中。结果列表中包含CharList[Char]

由于唯一满足这两者的类型是Any,因此X将为Any,而for-comprehension的结果为List[Any]