Reputation: 6065
Can you use collection.Map as the accumulator/return value of a fold?
For example:
Seq(1, 2, 3).foldLeft(collection.Map.empty[Int, Int]) {
case (map, i) => map.asInstanceOf[collection.Map[Int, Int]] + (i -> i)
}
Scala gives me the following type error:
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) }
Why is it enforcing use of collection.immutable.Map
instead of collection.Map
?
EDIT: The pointless casting is a bit misleading so I want to make my intent more clear. I am specifically using collection.Map
inside of the fold because it is the superclass of immutable.Map
and mutable.Map
. In reality, I am using a function inside of the fold that returns collection.Map
, consider:
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))
^
An answer given below does work: changing the start value from collection.Map.empty[Int, Int]
to collection.Map[Int, Int]()
. I'm not sure why this makes a difference though:
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)
Upvotes: 2
Views: 1500
Reputation: 16224
Edit
The method empty
returns this:
def empty[A, B]: immutable.Map[A, B] = immutable.Map.empty
That's why you have the error type, so, creating an object with ()
, will return to you the correct type, 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)
Upvotes: 1
Reputation: 1544
You don't have to cast it, since you've already defined the type:
Seq(1, 2, 3).foldLeft(collection.Map[Int, Int]()) {
case (map, i) => map + (i -> i)
}
Upvotes: 3