在 foldleft 中使用 collection.Map

Using collection.Map in foldleft

你可以使用 collection.Map 作为折叠的 accumulator/return 值吗?

例如:

Seq(1, 2, 3).foldLeft(collection.Map.empty[Int, Int]) { 
  case (map, i) => map.asInstanceOf[collection.Map[Int, Int]] + (i -> i)
}

Scala 给我以下类型错误:

 found   : scala.collection.Map[Int,Int]
 required: scala.collection.immutable.Map[Int,Int]
              Seq(1, 2, 3).foldLeft(collection.Map.empty[Int, Int]) { case (map, i) => map.asInstanceOf[collection.Map[Int, Int]] + (i -> i) }

为什么强制使用 collection.immutable.Map 而不是 collection.Map

编辑:毫无意义的转换有点误导,所以我想让我的意图更清楚。我特别在折叠内部使用 collection.Map,因为它是 immutable.Mapmutable.Map 的超类。实际上,我在 returns collection.Map 折叠内使用一个函数,考虑:

scala> def func(map: collection.Map[Int, Int]): collection.Map[Int, Int] = map
func: (map: scala.collection.Map[Int,Int])scala.collection.Map[Int,Int]

scala> Seq(1, 2, 3).foldLeft(collection.Map.empty[Int, Int])((map, i) => map + (i -> i))
res11: scala.collection.immutable.Map[Int,Int] = Map(1 -> 1, 2 -> 2, 3 -> 3)

scala> Seq(1, 2, 3).foldLeft(collection.Map.empty[Int, Int])((map, i) => func(map) + (i -> i))
<console>:9: error: type mismatch;
 found   : scala.collection.Map[Int,Int]
 required: scala.collection.immutable.Map[Int,Int]
              Seq(1, 2, 3).foldLeft(collection.Map.empty[Int, Int])((map, i) => func(map) + (i -> i))
                                                                                          ^

下面给出的答案确实有效:将起始值从 collection.Map.empty[Int, Int] 更改为 collection.Map[Int, Int]()。我不确定为什么这会有所不同:

scala> Seq(1, 2, 3).foldLeft(collection.Map[Int, Int]())((map, i) => func(map) + (i -> i))
res13: scala.collection.Map[Int,Int] = Map(1 -> 1, 2 -> 2, 3 -> 3)

您不必转换它,因为您已经定义了类型:

Seq(1, 2, 3).foldLeft(collection.Map[Int, Int]()) {
  case (map, i) => map + (i -> i)
}

Edit

方法emptyreturn是这样的:

def empty[A, B]: immutable.Map[A, B] = immutable.Map.empty

这就是你有错误类型的原因,因此,使用 () 创建一个对象,将 return 给你正确的类型,collection.Map[Int, Int]:

def func(map: collection.Map[Int, Int]): collection.Map[Int, Int] = map

Seq(1, 2, 3).foldLeft(collection.Map[Int, Int]())((res, i) =>
  res + (i -> i)
) 

Map(1 -> 1, 2 -> 2, 3 -> 3)