Apply Implicit Map Conversion

I tried implicit conversions in the following example:

val m: Map[Int, Int] = Map(10 -> "asd")  //fine
val mm: Map[Int, Int] = Map("asd" -> 20) //type mismatch; found: (String, Int) 
                                         //required: (Int, Int)

implicit def stringToInt(str: String): Int = 10

Why can't we apply implicit conversions to maps? Is there any way around this?

+4
source share
3 answers

This does not work because you are using ->which is the operator (inline):

implicit final class ArrowAssoc[A](self : A) extends scala.AnyVal {
  @scala.inline
  def ->[B](y : B) : scala.Tuple2[A, B] = { /* compiled code */ }
  def →[B](y : B) : scala.Tuple2[A, B] = { /* compiled code */ }
}

You can see that at the time of the evaluation, the BA is already “fixed”. Say you can (implicitly) convert the right side of a tuple using an operator ->:

implicit def stringToInt(str: String): Int = 10  
implicit def intToStr(str: Int): String = "a"

val a: Map[Int, Int] = Map(10 -> "asd") //fine
val b: Map[Int, Int] = Map("asd" -> 20) // error! cant change left side

val c: Map[String, String] = Map("asd" -> 20) // fine 
val d: Map[String, String] = Map(10 -> "asd") // error! cant change left side

Because of the compiler’s complexity associated with using the operator ->, @Jorg's solution works in one direction, but not in the other:

implicit def tupleIntifier(t: (String, Int)) = (10, 10)
implicit def tupleIntifier2(t: (Int, String)) = (10, 10)

val a: Map[Int, Int] = Map("asd" -> 20) // uses tupleIntifier
val b: Map[Int, Int] = Map(10 -> "asd") // fails!!

, -> (key, value), :

val a: Map[Int, Int] = Map((10, "asd"))
val b: Map[Int, Int] = Map(("asd", 20))

implicit def stringToInt(str: String): Int = 15

println(a) // prints Map(10 -> 15)
println(b) // prints Map(15 -> 20)
+5

, , :

error: type mismatch;
found   : (String, Int)
required: (Int, Int)
      val mm: Map[Int, Int] = Map("asd" -> 20)
                                        ^

String Int, (String, Int) (Int, Int). , :

implicit def tupleIntifier[T](t: (String, T)) = (10, t._2)

val mm: Map[Int, Int] = Map("asd" -> 20)
//=> mm: Map[Int,Int] = Map(10 -> 20)

Voila! .

+2

, , Scala, String Int , , . , , , , . , , Int . . . ?

+1
source

Source: https://habr.com/ru/post/1660515/


All Articles