【发布时间】:2021-12-31 00:48:04
【问题描述】:
我一直在阅读 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")
所以,我假设编译器看到 2 个相同的隐式实例并抱怨。我可以通过显式添加作为参数传递的 PrintStream 作为日志的第二个参数来使编译器静音:
def logTime(m: String)(implicit o: PrintStream): Unit =
log(s"${new Date().getTime} : $m")(o)
这行得通,但我错过了什么吗?为什么 logTime() 的主体内部会出现混乱?我认为布鲁诺暗示来自调用者的隐含将被投射到方法的范围内。他的示例没有在 log() 调用中添加额外的参数。为什么scalac将这些视为2?我想我假设外部方法的隐含会“隐藏” val。不是这样。
如果有人能解释我为什么看到这个,将不胜感激。
【问题讨论】:
-
在
logTime内部有两个有效的类型为PrintStream的隐式值实例(顺便说一句,这是一种可怕的隐式类型),这使得它模棱两可,这是一个编译错误;期间。