Search code examples
functionscalacurryingimplicits

scala implicit class method type mismatch in reduce vs non-implicit method with function currying


Problem:

Something about implicit class, confuses reduce(). When inside implicit class, compiler complains on reduce() second parameter. but when same code is inside non-implicit method it compiles and works fine.

What am I missing about implicit classes?

Code:

object ImpliCurri {
    implicit class MySeq[Int](val l: Seq[Int]) {
        //not compiling
        final def mapSum(f:Int=>Int):Int = {
            l.map(x=>f(x)).reduce(_+_)
       //compile error on reduce: Type mismatch. Expected String, fount Int
        }
    }

    // works fine
    def mySum(l:Seq[Int], f:Int=>Int):Int = {
        l.map(x=>f(x)).reduce(_+_)
        // compiles and works no issues
    }
}

Solution

  • It doesn't actually have anything to do with implicits. You get the same error if it's just a regular class.

    The reason is that you have declared a generic type: MySeq[Int] that just happens to be called Int. So when you say f: Int => Int you think "Oh, that's an integer" and the compiler thinks, "Oh, that means you could fill in any type there!". (Replace all your Ints with A and it would work the same.)

    Now the compiler is in a bind. What + can you apply to any pair of types? Well, you can convert anything to a String, and + is defined on a String. So you get a very misleading error message when the compiler realizes that this approach won't work.

    Just drop the [Int] and all your Ints will actually mean what you think they mean, and the implicit class version will work fine.