Scala:隐式、子类化和成员类型

标签 scala

假设我们想使用类型类来实现 pretty-print :

trait Printer[T] {def print(t: T)}

对于整数的默认实现:

implicit object IntPrinter extends Printer[Int] {
    override def print(i : Int): Unit = println(i)
}

我们要打印的具体类型是:

trait Foo {
    type K
    val k: K
}

class IntFoo extends Foo {
    override type K = Int
    override val k = 123
}

很酷。现在我想为所有具有可打印 Ks 的 Foos 构建打印机

implicit def fooPrinter[FP <: Foo](implicit ev: Printer[FP#K]): Printer[FP] =
    new Printer[FP] {
        override def print(f: FP): Unit = {
            Predef.print("Foo: ")
            ev.print(f.k)
        }
    }

让我们检查隐式是否已解析:

def main(args: Array[String]) {
    implicitly[Printer[Int]]
    implicitly[Printer[IntFoo]]
}

scalac 2.11.2 说:

diverging implicit expansion for type Sandbox.Printer[Int]
    starting with method fooPrinter in object Sandbox
        implicitly[Printer[Int]]

什么?

好的,让我们重写 fooPrinter:

implicit def fooPrinter[KP, FP <: Foo {type K = KP}](implicit ev: Printer[KP]) =
    new Printer[FP] {
        override def print(f: FP): Unit = {
            Predef.print("Foo: ")
            ev.print(f.k)
        }
    }

这在 2.11 中有效,但第一种方法有什么问题? 不幸的是我们在 2.10,第二个解决方案仍然不起作用。它会一直编译,直到我们再添加一台类似的打印机

implicit object StringPrinter extends Printer[String] {
    override def print(s : String): Unit = println(s)
}

它神秘地打破了 Printer[IntFoo] 隐式:

could not find implicit value for parameter e:   
    Sandbox.Printer[Sandbox.IntFoo]

编译器错误?

最佳答案

隐式声明的顺序很重要。在您的源代码中重新排序来自

的原始代码
implicit object IntPrinter ...
...
implicit def fooPrinter ...

implicit def fooPrinter ...
...
implicit object IntPrinter ...

关于Scala:隐式、子类化和成员类型,我们在Stack Overflow上找到一个类似的问题: https://stackoverflow.com/questions/26152320/

相关文章:

scala - 编译小睡 - 当编译准备好时,如何让 sbt 响铃?

scala - Scala 3 宏中的显式类型转换

scala - 如何用akka和sbt开发?

multithreading - 为什么 akka actor 与 thread 如此不同

scala - 使用隐式将类型参数视为数字

scala - 如何使用 udf 将空列添加到 Spark 中的复杂数组结构

scala - 两个异常 "at the same time",处理这种情况的正确方法是什么?

scala - 可观察的 takeUntil 行为不当

list - Scala的 '::'运算符,它是如何工作的?

scala - 如何将 json4s 库添加到 Scala