折叠的奇怪行为

时间:2013-05-20 21:24:03

标签: scala type-inference

我做错了什么? String来自哪里?

Scala code runner版本2.9.2 - 版权所有2002-2011,LAMP / EPFL

scala> List(1).fold(Map()) { (m, x) => m + (x -> 1) }
<console>:9: error: type mismatch;
 found   : (Any, Int)
 required: String
              List(1).fold(Map()) { (m, x) => m + (x -> 1) }
                                                     ^

scala> List(1).foldLeft(Map()) { (m, x) => m + (x -> 1) }
<console>:9: error: type mismatch;
 found   : (Int, Int)
 required: (Nothing, Nothing)
              List(1).foldLeft(Map()) { (m, x) => m + (x -> 1) }
                                                         ^

1 个答案:

答案 0 :(得分:4)

我会以相反的顺序回答:

  • 由于第二个错误,您需要帮助键入推理:Scala编译器无法知道Map()的类型(它需要期待第二个参数组,即操作符,它不能do),因此它推断为Map[Nothing, Nothing]()。然后尝试将(Int, Int)添加到Map[Nothing, Nothing]显然不起作用。

  • 对于第一个错误,您使用fold,这需要二进制运算符,类型为(A,A) => A,所以在您的情况下可能是(Int, Int) => Int,这不是您的意思正在寻找,因为您尝试折叠成完全不同的类型:foldLeftfoldRight可以做到这一点。

    修改:它正在寻找String,因为它认为mx必须共享相同的类型,因此它们的类型为{{ 1}}(他们唯一的常见超类型),它没有Any方法,但它有一个隐式转换,为... +串联提供它;因此,它会将String转换为m,然后在String的另一侧查找另一个String。我知道,这很难过。

您只需在+上注释类型:

Map

或者,以更清晰的方式表明意图:

scala> List(1).foldLeft(Map[Int, Int]()) { (m, x) => m + (x -> 1) }
res8: scala.collection.immutable.Map[Int,Int] = Map(1 -> 1)