- html - 出于某种原因,IE8 对我的 Sass 文件中继承的 html5 CSS 不友好?
- JMeter 在响应断言中使用 span 标签的问题
- html - 在 :hover and :active? 上具有不同效果的 CSS 动画
- html - 相对于居中的 html 内容固定的 CSS 重复背景?
我使用的是 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
上存在歧义。 (为什么?)
如果我注释掉 rabbitHoleInHole
,scalac 会编译并返回“Rabbit 在 Hole 包对象中找到了洞”。 (本地作用域中的隐含值不应该优先吗?)
如果我随后注释掉 rabbitHoleInHolePackage
,scalac 会提示 rabbitHoleInOuterTest
和 rabbitHoleInInnerTest
上的歧义。 (为什么?在 eed3si9n 的文章中,下面列出了 url,他发现隐式 btw 内部和外部范围可以采取不同的优先级。)
如果我随后注释掉 rabbitHoleInInnerTest
,scalac 会编译并返回“Rabbit 发现外部测试对象中的洞”。
正如您所看到的,上述行为根本不遵循我在隐式解析中阅读的规则。我只描述了在注释/取消注释实例时可以执行的一小部分组合,其中大多数确实非常奇怪 - 而且我还没有讨论导入和子类。
我已阅读并观看 presentation by suereth , stackoverflow answer by sobral ,和a very elaborate revisit by eed3si9n ,但我仍然完全困惑。
最佳答案
让我们从包对象中的隐式和禁用的类型类伴生开始:
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 引用文献 7.2 中的精确定义。
The implicit scope of a type T consists of all companion modules (§5.4) of classes that are associated with the implicit parameter’s type. Here, we say a class C is associated with a type T, if it is a base class (§5.1.2) of some part of T.
The parts of a type
T
are:
- if
T
is a compound typeT1 with ... with Tn
, the union of the parts ofT1, ..., Tn
, as well asT
itself,- if
T
is a parameterized typeS[T1, ..., Tn]
, the union of the parts ofS
andT1,...,Tn
,- if
T
is a singleton typep.type
, the parts of the type ofp
,- if
T
is a type projectionS#U
, the parts ofS
as well asT
itself,- in all other cases, just
T
itself.
我们正在寻找rabbit.TC
。从类型系统的角度来看,这是: rabbit.type#TC
的简写,其中rabbit.type
是表示包的类型,就像它是一个常规对象一样。调用规则 4,为我们提供零件 TC
和p.type
.
那么,这一切意味着什么?简而言之,包对象中的隐式成员也是隐式作用域的一部分!
在上面的示例中,这为我们在隐式搜索的第二阶段提供了明确的选择。
其他例子可以用同样的方式解释。
总结:
更新
在 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])
}
}
}
关于scala - scala 2.10.x 中的隐式解析。这是怎么回事?,我们在Stack Overflow上找到一个类似的问题: https://stackoverflow.com/questions/10763511/
我是一名优秀的程序员,十分优秀!