Scala 隐式参数投影冲突、"Ambigious Implicit Values"错误



我一直在阅读Bruno的TypeClasses论文,他提到参数列表中的隐词被投影/传播到隐式范围中。我以这个代码为例:

package theory
import cats.implicits.toShow
import java.io.PrintStream
import java.util.Date
object Equality extends App {
import cats.Eq
//  assert(123 == "123")
println(Eq.eqv(123, 123).show)
implicit val out: PrintStream = System.out
def log(m: String)(implicit o: PrintStream ): Unit =
o.println(m)
def logTime(m: String)(implicit  o: PrintStream): Unit =
log(s"${new Date().getTime} : $m")
}

关键是该代码将不编译,带有:

ambiguous implicit values:
both value out in object Equality of type java.io.PrintStream
and value o of type java.io.PrintStream
match expected type java.io.PrintStream
log(s"${new Date().getTime} : $m")

因此,我假设编译器看到了两个相同的隐式实例并进行了抱怨。通过显式添加作为参数传递的PrintStream作为日志的第二个参数,我可以使编译器静音:

def logTime(m: String)(implicit  o: PrintStream): Unit =
log(s"${new Date().getTime} : $m")(o)

这很管用,但我是不是遗漏了什么?为什么logTime((的主体内部存在混乱?我认为Bruno是在暗示来自调用者的隐式将被投影到方法的范围中。他的例子没有将额外的参数添加到log((调用中。为什么scalac把这些看作2?我想我假设从外部隐含的方法将";隐藏";val out。并非如此。

如果有人能解释我为什么看到这个,我将不胜感激。

回想一下,隐式参数的值是在调用站点确定的。这就是为什么。。。

Equality.log("log this")

除非将适当类型的隐式值引入作用域,否则不会编译。

implicit val ps: PrintStream = ...
Equality.log("log this")

logTime()定义代码是log()方法的调用站点,由于它是在Equality对象中定义的,因此它具有可用的implicit val out值。但它也是从其调用站点传递的相同类型的implicit o值的接收方。因此产生了歧义。编译器应该向log()方法发送implicit out值还是implicit o值?

现在,接收到的隐式值(来自调用站点(同时被分配给本地标识符o,并插入到本地隐式命名空间中,这似乎有点奇怪。事实证明,Scala-3已经修改了这种行为,即使没有新的given/using语法,您的代码也能顺利编译。(我假设implicit out值被传递给log()方法,而不是接收到的o值。(

相关内容

  • 没有找到相关文章

最新更新