为什么带有映射的隐式会产生 Range 语句错误?

Why does an implicit with a map yield a Range statement error?

对于下面的 MRE,我希望得到以下输出:

$ scala mre.scala
1
object Main {
  def main(args: Array[String]): Unit = {
    implicit val thing = List[String]().map(_.to(List))
    for (x <- 1 to 1) {
        println(x)
    }
  }
}

但是我得到的是以下内容

$ scala mre.scala
mre.scala:4: error: type mismatch;
 found   : Int(1)
 required: scala.collection.Factory[Char,?]
    for (x <- 1 to 1) {

如果我删除 implicit.map(_.to(List)) 那么它会按预期工作。

这到底是怎么回事?我什至不知道从哪里开始。

$ scala --version
Scala code runner version 2.13.7 -- Copyright 2002-2021, LAMP/EPFL and Lightbend, Inc.

有根据的猜测(99% 的确定性):任何集合都会扩展 (Partial)Function 因此,通过使集合隐式化,您将提供隐式转换(因为任何一元 implicit def OR隐式函数是隐式转换):

// this
implicit val thing = List[String]().map(_.to(List))
// implies this
implicit def intToCharList(idx: Int): List[Char]] =  thing(idx)

然后这里:

 1 to 1

你有歧义:可能是:

  • 扩展方法 .to(Int) Int
  • Int 隐式转换后 List 上的 .to(CollectionType) 普通方法(自 Scala 2.13 起)

如果编译器选择后者,那么你会得到类似

的东西
thing(1).to(1) // .to expects collection factory and got 1 instead 

这会触发您看到的错误。它可能会选择后者,因为你在同一范围内声明了你的隐式,而 richInt implicit conversionscala.Predef 中的 LowPriorityImplicit 中声明,所以 Scala 会更喜欢你的。

在 Scala 3 中,隐式转换是 Function 子类型 ,因此不会发生此问题。在 Scala 2 中,我只能强烈建议不要使 any 集合隐式化。