简体   繁体   中英

Using implicits for scala map keys

Can someone tell me why, as shown below, an implicit conversion works when simply creating a KeyVal object but does not work when creating a key in a Map that is a KeyVal.

Thank you.

object o {
  case class KeyVal(i: Int)
  object KeyVal {
    implicit def strToKeyVal(s:String) = KeyVal(s.toInt)
  }
}

import o._

val x : KeyVal = "1"  // Works fine to create a KeyVal

val x : Map[KeyVal, String] = Map("1" -> "One") // Type Mismatch: found (String, String), wants (KeyVal, String)

Scala compiler is not an allmighty thing, and it cant resolve all types of type errors. How should it convert (String, String) tuple to (KeyVal, String) tuple and why not to (String, KeyVal) or (KeyVal, KeyVal) . Your implicit conversion converts String to KeyVal , but not a (String, String) to KeyVal . If you add this implicit conversion to the companion object:

implicit def strToKeyVal(s: (String, String)): (KeyVal, String) = (KeyVal(s._1.toInt), s._2)

everything would work fine

It's just a matter of timing. By the time the type of the Map is considered, you no longer have a String , but a (String, String) tuple. This happens because -> is an operator that is applied first, and then its result is returned for Map .

If you avoid using that operator, it works:

val x : Map[KeyVal, String] = Map(("1", "One"))

The technical post webpages of this site follow the CC BY-SA 4.0 protocol. If you need to reprint, please indicate the site URL or the original address.Any question please contact:yoyou2525@163.com.

 
粤ICP备18138465号  © 2020-2024 STACKOOM.COM