当 scalac 在 Map[K,V] 和 Traversable[T] 之间选择时,隐式是不明确的

Implicit is ambiguous when scalac chooses between Map[K,V] and Traversable[T]

在扩展 MongoDB 序列化库时,我偶然发现了隐含问题。

在下面提到的示例项目中,scalac 无法在 Map[K,V]Traversable[T] 的隐式之间进行选择。启用日志记录后我收到的警告是

[info] ambiguous implicit values:
[info]  both method mapSetterStringKey in object BsonWritable of type [V](implicit vw: com.osinka.subset.BsonWritable[V])com.osinka.subset.BsonWritable[Map[String,V]]
[info]  and method seqSetter in object BsonWritable of type [T](implicit w: com.osinka.subset.BsonWritable[T])com.osinka.subset.BsonWritable[Traversable[T]]
[info]  match expected type com.osinka.subset.BsonWritable[scala.collection.immutable.Map[String,List[Double]]]
[info]     val bson = DBO(name -> testMap)()
[info]                         ^

如果您取消注释对象 BsonMarshallers 中的编组器,它会起作用。但是当在 com.osinka.subset.BsonWritable.

中指定两个隐式时它会失败

您能否解释一下为什么 scalac 没有为 Map 选择更具体的隐式?

https://github.com/cppexpert/subset2-implicit-issue

如果我理解你的问题,Programming in Scala, First Edition 中的这一点可能会解释它。

Non-Ambiguity Rule: An implicit conversion is only inserted if there is no other possible conversion to insert. If the compiler has two options to fix x + y, say using either convert1(x) + y or convert2(x) + y, then it will report an error and refuse to choose between them. It would be possible to define some kind of "best match" rule that prefers some conversions over others. However, such choices lead to really obscure code. Imagine the compiler chooses convert2, but you are new to the file and are only aware of convert1—you could spend a lot of time thinking a different conversion had been applied!

In cases like this, one option is to remove one of the imported implicits so that the ambiguity is removed. If you prefer convert2, then remove the import of convert1. Alternatively, you can write your desired conversion explicitly: convert2(x) + y.