Take the 2-minute tour ×

What am I doing wrong? Where does String come from?

Scala code runner version 2.9.2 -- Copyright 2002-2011, LAMP/EPFL

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

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

1 Answer 1

up vote 3 down vote accepted

I'll answer in reverse order:

  • With the second error, your need to help type inference: the Scala compiler cannot know the type of Map() (it would need to look forward to the second parameter group, the operator, which it cannot do), so it infers it as Map[Nothing, Nothing](). And then trying to add an (Int, Int) to a Map[Nothing, Nothing] obviously won't work.

  • With the first error, you use fold, which requires a binary operator, with type (A,A) => A, so in your case probably (Int, Int) => Int, which isn't what you are looking for since your try to fold into a completely different type: foldLeft and foldRight can do that, however.

    Edit: it is looking for a String because it believes that m and x have to share the same type, so they have type Any (their only common supertype), which doesn't have a + method, but it has an implicit conversion that provides it for... String concatenation ; so it converts m to a String and then looks for another String on the other side of +. I know, this is sad.

You just need to annotate the types on Map:

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

Or, to show the intent in a clearer way:

scala> List(1).foldLeft(Map.empty[Int, Int]) { (m, x) => m + (x -> 1) }
share|improve this answer
Thank you, I actually tried Map[Int, Int]() with fold but was confused by complaining about String and haven't tried it with foldLeft. Don't understand though why inference doesn't work for fold: scala> List(i).fold(Map[Int, Int]())(_) res18: ((Any, Any) => Any) => Any = <function1> and works for foldLeft, it could produce more meaningful error message. –  Victor Moroz May 20 '13 at 22:09
@VictorMoroz that's probably because of the real definition of fold for a List[A] : def fold[B >: A](z: B)(op: (B, B) => B): B. The binary operator is only restricted to work on A or any supertype B of A. In your case B can be Int or any of its parents, and it seems like inference picks the most generic one: Any. foldLeft doesn't bother itself with supertypes, there is only A and a target type, so the inference just works. –  gourlaysama May 20 '13 at 22:21
Yes, error messages aren't always very helpful when type inference is involved. There is so much dark magic going on in there... –  gourlaysama May 20 '13 at 22:31
I think I understand it now. Because I had List[Int] and passed Map[Int, Int]() to fold scala found the nearest common superclass for Int and Map[Int, Int] which is Any. That's why signature is ((Any, Any) => Any) => Any. And somehow + for Any requires String (most probably via implicit conversion as I can't find + for Any). List(1).fold(1)(_) has signature ((Int, Int) => Int) => Int as expected. –  Victor Moroz May 20 '13 at 22:44
@VictorMoroz yes, there is an implicit conversion in Predef from Any to StringAdd, which has the + method. You're right about the common superclass thing, I got mixed up in my comment... –  gourlaysama May 20 '13 at 22:50

Your Answer


