Johann
Johann

Reputation: 25

Return type in scala generic

I am pretty new to scala, and i have hard time with generic in some case. I try to find simple example to illustrate my issue

let's start by setting 3 simple maps

scala> val map1 = Map[String, String]("A" -> "toto", "B" -> "tutu")
map1: scala.collection.immutable.Map[String,String] = Map(A -> toto, B -> tutu)

scala> val map2 = Map[String, Int]("B" -> 2)
map2: scala.collection.immutable.Map[String,Int] = Map(B -> 2)

scala> val map3 = Map[String, String]("A" -> "foo")
map3: scala.collection.immutable.Map[String,String] = Map(A -> foo)

if i merge using ++

scala> map1 ++ map2
res0: scala.collection.immutable.Map[String,Any] = Map(A -> toto, B -> 2)

My map became [String, Any] which is what i want to reproduce

I create new method in Map class

object MapUtils {
    implicit class utils[K, V](map: Map[K, V]) {
        def myUselessMethod(merge: Map[K, V]): Map[K, V] = {
            map ++ merge
        }
    }
}
import MapUtils._

scala> map1 myUselessMethod map3
res4: Map[String,String] = Map(A -> foo, B -> tutu)

scala> map1 myUselessMethod map2
<console>:18: error: type mismatch;
found   : scala.collection.immutable.Map[String,Int]
required: Map[String,String]
        map1 myUselessMethod map2

How should i define my method so that it can return [String, Any]

I also checked scala MAP API to see if i can have some indications https://www.scala-lang.org/api/2.12.3/scala/collection/Map.html but

++[B >: (K, V), That](that: GenTraversableOnce[B])(implicit bf: 
CanBuildFrom[Map[K, V], B, That]): That

is somehow indecipherable for me...

Thank you

Upvotes: 1

Views: 143

Answers (1)

Andrey Tyukin
Andrey Tyukin

Reputation: 44908

Just give the compiler some slack in the return type:

object MapUtils {
    implicit class utils[K, V](map: Map[K, V]) {
        def myUselessMethod[L >: V](merge: Map[K, L]): Map[K, L] = {
            map ++ merge
        }
    }
}
import MapUtils._

val map1 = Map[String, String]("A" -> "toto", "B" -> "tutu")
val map2 = Map[String, Int]("B" -> 2)

map1 myUselessMethod map2

Now it will infer the least upper bound L of V and the value type of the merge-argument map. In case of Int and String, L would be inferred to be Any.

Upvotes: 1

Related Questions