[英]What is the implicit resolution sequence in this “simple” ScalaZ tutorial code example?
下面的代码片段取自此 ScalaZ教程。
在评估代码示例底部的10.truthy
时,我无法弄清楚隐式解析规则是如何应用的。
我认为 - 我明白的事情如下:
1)隐含值intCanTruthy
是CanTruthy[A]
的匿名子类的实例,它CanTruthy[A]
内容定义Int
-s的truthys
方法:
scala> implicit val intCanTruthy: CanTruthy[Int] = CanTruthy.truthys({
case 0 => false
case _ => true
})
intCanTruthy: CanTruthy[Int] = CanTruthy$$anon$1@71780051
2)当评估10.truthy
, toCanIsTruthyOps
隐式转换方法在范围内,因此当编译器看到Int
没有truthy
方法时,它将尝试使用这种隐式转换方法。 所以编译器会尝试寻找它转换一些隐式转换方法10
进入的对象不具有truthy
方法及其它会尝试toCanIsTruthyOps
这种转换是。
3)我怀疑当编译器在10
上尝试toCanIsTruthyOps
隐式转换时,可能会以某种方式使用隐式值intCanTruthy
。
但这是我真正迷失的地方。 我只是没有看到隐含的解决方法过程如何进行。 接下来发生什么 ? 怎么样,为什么?
换句话说,我不知道什么是隐式解析序列,它允许编译器在评估10.truthy
时找到truthy
方法的实现。
问题 :
如何将10
转换为具有正确truthy
方法的某个对象?
那个对象是什么?
那个对象来自哪里?
有人可以详细解释在评估10.truthy
时隐式解决方案是如何发生的吗?
CanTruthy
中的自我类型 { self => ...
CanTruthy
在隐式解决过程中发挥作用?
scala> :paste
// Entering paste mode (ctrl-D to finish)
trait CanTruthy[A] { self =>
/** @return true, if `a` is truthy. */
def truthys(a: A): Boolean
}
object CanTruthy {
def apply[A](implicit ev: CanTruthy[A]): CanTruthy[A] = ev
def truthys[A](f: A => Boolean): CanTruthy[A] = new CanTruthy[A] {
def truthys(a: A): Boolean = f(a)
}
}
trait CanTruthyOps[A] {
def self: A
implicit def F: CanTruthy[A]
final def truthy: Boolean = F.truthys(self)
}
object ToCanIsTruthyOps {
implicit def toCanIsTruthyOps[A](v: A)(implicit ev: CanTruthy[A]) =
new CanTruthyOps[A] {
def self = v
implicit def F: CanTruthy[A] = ev
}
}
// Exiting paste mode, now interpreting.
defined trait CanTruthy
defined module CanTruthy
defined trait CanTruthyOps
defined module ToCanIsTruthyOps
尝试10
上的类型类:
scala> import ToCanIsTruthyOps._
import ToCanIsTruthyOps._
scala> implicit val intCanTruthy: CanTruthy[Int] = CanTruthy.truthys({
case 0 => false
case _ => true
})
intCanTruthy: CanTruthy[Int] = CanTruthy$$anon$1@71780051
scala> 10.truthy
res6: Boolean = true
首先,感谢您粘贴一个完全独立的示例。
如何将
10
转换为具有正确truthy
方法的某个对象?
当对类型A
不提供该方法的值调用方法时,必须启动隐式转换 ,即在范围内必须有方法或函数,其中签名A => B
其中B
具有所讨论的方法( truthy
)。 在转换方法的情况下,它可能要求额外的隐含参数 ,这些参数将被相应地查找。
转换方法是toCanIsTruthyOps
,通过导入ToCanIsTruthyOps
的内容使其可用。 上述句子中的B
型是CanTruthyOps
,转换方法是toCanIsTruthyOps
。 只要找到隐式类型类证据参数CanTruthy
它就可以被编译器调用。 因此,由于type A = Int
,如果调用10.truthy
将成功,编译器必须找到CanTruthy[Int]
类型的隐式值。
它在几个地方寻找这样的价值。 它可能位于Int
(不存在)的伴随对象或CanTruthy
的伴随对象中,或者显式导入到当前范围中。 这里使用最后一种情况。 您明确创建了隐式值intCanTruthy
,现在找到该值。 就是这样。
那个对象是什么?
将有一个CanTruthyOps
的临时实例,其目的仅仅是在证据类型类值上调用truthys
(这里是你的intCanTruthy
)。
那个对象来自哪里?
它在查找隐式转换时发现Int => CanTruthyOps[Int]
。 转换执行该对象的实例化。
有人可以详细解释在评估
10.truthy
时隐式解决方案是如何发生的吗?
请参阅上面第一个问题的答案。 或者作为显式代码:
type A = Int
val v: A = 10
val ev: CanTruthy[A] = intCanTruthy
val ops: CanTruthyOps[A] = ToCanIsTruthyOps.toCanIsTruthyOps(v)(ev)
ops.truthy
CanTruthy
中的自我类型{ self => ...
CanTruthy
在隐式解决过程中发挥作用?
它与隐式解决方案无关。 事实上,在你们的例子trait CanTruthy
中, self
充当一个别名this
并没有使用连,所以你可以只将其删除。
将任何A
转换为具有truthy
方法的CanTruthyOps[T]
的方法的truthy
是:
implicit def toCanIsTruthyOps[A](v: A)(implicit ev: CanTruthy[A])
这意味着它不会转换任何A
而只会转换那些定义了CanTruthy[A]
的CanTruthy[A]
,这就是implicit ev
参数的用途。 这意味着,作为将10
映射到具有.truthy
方法的事物的过程的一部分,在完成包装之前也会intCanTruthy
。 因此,当10
被隐式转换为具有truthy
方法的东西时, intCanTruthy
实例将被查找并作为CanTruthyOps
的F
属性存储起来:
implicit def F: CanTruthy[A] = ev
(实际上我不知道为什么implicit
在那里是必要的; truthy()
将明确转向F
F.truthys(self)
至于隐式解析是如何工作的,最好还是查找详细描述该过程的文档。
声明:本站的技术帖子网页,遵循CC BY-SA 4.0协议,如果您需要转载,请注明本站网址或者原文地址。任何问题请咨询:yoyou2525@163.com.