Warning: file_get_contents(/data/phpspider/zhask/data//catemap/2/scala/18.json): failed to open stream: No such file or directory in /data/phpspider/zhask/libs/function.php on line 167

Warning: Invalid argument supplied for foreach() in /data/phpspider/zhask/libs/tag.function.php on line 1116

Notice: Undefined index: in /data/phpspider/zhask/libs/function.php on line 180

Warning: array_chunk() expects parameter 1 to be array, null given in /data/phpspider/zhask/libs/function.php on line 181
Scala:隐式、子类化和成员类型_Scala - Fatal编程技术网

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

Scala:隐式、子类化和成员类型,scala,Scala,假设我们希望使用类型类实现漂亮的打印: trait Printer[T] {def print(t: T)} 使用ints的默认实现: 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

假设我们希望使用类型类实现漂亮的打印:

trait Printer[T] {def print(t: T)}
使用ints的默认实现:

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的FOO构建打印机

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)
        }
    }
scalac 2.11.2说:

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

好的,让我们重写打印机:

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)
        }
    }
它神秘地破坏了打印机[IntFoo]隐式:

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

编译器错误?

隐式声明的顺序很重要。在源代码中,对源代码重新排序

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


移动它修复了2.11上fooPrinter的第一个定义(并在2.10上导致了非常奇怪的bug)。如果顺序不同,它们为什么会冲突?我对隐式的看法是,如果有一点疑问,那么它根本不起作用。它是由偏执狂设计的,这样它就不会意外地解决一些你可能没有预料到的问题。。。但这并不能回答你的问题。我假设编译器已经找到一个隐式定义打印机[FP],它可能只通过查看其返回值返回打印机[Int]。在这一点上,它可能不会检查FP。隐式解析如此脆弱的另一个原因也是编译速度。正如您所想象的,如果它真的尝试评估所有可能的隐式定义,它可能会成为一场指数回溯噩梦。但透明度可能更重要。如果我错了,请纠正我,但应该是线性的,因为编译器并没有尝试所有隐式的组合。是的,我认为正确性和透明度应该优先于编译速度:)你可能是对的,这取决于算法的聪明程度。但无论如何,编译器肯定不会真正尝试所有可能的组合。因此,在某些情况下,隐式解析“应该”只通过查看代码就能起作用,但由于那些偏执的规则,它不能起作用。
could not find implicit value for parameter e:   
    Sandbox.Printer[Sandbox.IntFoo]
implicit object IntPrinter ...
...
implicit def fooPrinter ...
implicit def fooPrinter ...
...
implicit object IntPrinter ...