scala 2.10.x中的隐式解析.这是怎么回事?
我使用
scala 2.10.0-snapshot日期(20120522)并具有以下
Scala文件:
这个定义了类型类和基本的类型类实例: package com.netgents.typeclass.hole case class Rabbit trait Hole[A] { def findHole(x: A): String } object Hole { def apply[A: Hole] = implicitly[Hole[A]] implicit val rabbitHoleInHole = new Hole[Rabbit] { def findHole(x: Rabbit) = "Rabbit found the hole in Hole companion object" } } 这是包对象: package com.netgents.typeclass package object hole { def findHole[A: Hole](x: A) = Hole[A].findHole(x) implicit val rabbitHoleInHolePackage = new Hole[Rabbit] { def findHole(x: Rabbit) = "Rabbit found the hole in Hole package object" } } 这是测试: package com.netgents.typeclass.hole object Test extends App { implicit val rabbitHoleInOuterTest = new Hole[Rabbit] { def findHole(x: Rabbit) = "Rabbit found the hole in outer Test object" } { implicit val rabbitHoleInInnerTest = new Hole[Rabbit] { def findHole(x: Rabbit) = "Rabbit found the hole in inner Test object" } println(findHole(Rabbit())) } } 如您所见,Hole是一个简单的类型类,它定义了Rabbit试图找到的方法.我试图找出隐含的解决方案规则. >所有四个类型类实例都没有注释,scalac抱怨rabbitHoleInHolePackage和rabbitHoleInHole的含糊不清. (为什么?) 正如您所看到的,上述行为并未遵循我在隐式解析中阅读的规则.我只描述了你在评论/取消注释实例时可以做的一小部分组合,其中大多数确实非常奇怪 – 我还没有进入导入和子类. 我已经阅读并观看了presentation by suereth,stackoverflow answer by sobral和a very elaborate revisit by eed3si9n,但我仍然感到困惑. 解决方法
让我们从包对象中的implicits和禁用的类型类伴随开始:
package rabbit { trait TC object Test extends App { implicit object testInstance1 extends TC { override def toString = "test1" } { implicit object testInstance2 extends TC { override def toString = "test2" } println(implicitly[TC]) } } } Scalac查找范围内的任何含义,找到testInstance1和testInstance2.一个人在一个更紧凑的范围内这一事实只有在它们具有相同名称时才有意义 – 正常的阴影规则适用.我们选择了不同的名称,并且没有隐含的比另一个更具体,因此正确报告了歧义. 让我们尝试另一个例子,这次我们将在本地范围内对照包对象中的一个隐含. package rabbit { object `package` { implicit object packageInstance extends TC { override def toString = "package" } } trait TC object Test extends App { { implicit object testInstance2 extends TC { override def toString = "test2" } println(implicitly[TC]) } } } 这里发生了什么?与之前一样,隐式搜索的第一阶段考虑了呼叫站点范围内的所有隐含.在这种情况下,我们有testInstance2和packageInstance.这些是模糊的,但在报告该错误之前,第二阶段开始,并搜索TC的隐含范围. 但这里的隐含范围是什么? TC甚至没有配套对象?我们需要在Scala Reference的7.2中查看精确的定义.
我们正在寻找兔子.TC.从类型系统的角度来看,这是一个简写:rabbit.type#TC,其中rabbit.type是表示包的类型,就像它是一个常规对象一样.调用规则4,为我们提供TC和p.type部分. 那么,这一切意味着什么呢?简单地说,包对象中的隐式成员也是隐式作用域的一部分! 在上面的示例中,这为隐式搜索的第二阶段提供了明确的选择. 其他例子可以用同样的方式解释. 综上所述: >隐式搜索分两个阶段进行.通常的导入和阴影规则决定候选人名单. UPDATE 在Scala 2.9.2中,行为是不同的和错误的. package rabbit { trait TC object Test extends App { implicit object testInstance1 extends TC { override def toString = "test1" } { implicit object testInstance2 extends TC { override def toString = "test2" } // wrongly considered non-ambiguous in 2.9.2. The sub-class rule // incorrectly considers: // // isProperSubClassOrObject(value <local Test>,object Test) // isProperSubClassOrObject(value <local Test>,{object Test}.linkedClassOfClass) // isProperSubClassOrObject(value <local Test>,<none>) // (value <local Test>) isSubClass <none> // <notype> baseTypeIndex <none> >= 0 // 0 >= 0 // true // true // true // true // // 2.10.x correctly reports the ambiguity,since the fix for // // https://issues.scala-lang.org/browse/SI-5354?focusedCommentId=57914#comment-57914 // https://github.com/scala/scala/commit/6975b4888d // println(implicitly[TC]) } } } (编辑:李大同) 【声明】本站内容均来自网络,其相关言论仅代表作者个人观点,不代表本站立场。若无意侵犯到您的权利,请及时与联系站长删除相关内容! |