这个"简单"ScalaZ教程代码示例中的隐式解析序列是什么?

jhe*_*dus 4 scala implicit implicit-conversion scalaz

下面的代码片段取自 ScalaZ教程.

10.truthy在代码示例的底部进行评估时,我无法弄清楚如何应用隐式解析规则.

我认为 - 我明白的事情如下:

1)隐式值intCanTruthy是匿名子类的一个实例,CanTruthy[A]它根据以下内容定义-s 的truthys方法Int:

scala> implicit val intCanTruthy: CanTruthy[Int] = CanTruthy.truthys({
         case 0 => false
         case _ => true
       })
intCanTruthy: CanTruthy[Int] = CanTruthy$$anon$1@71780051
Run Code Online (Sandbox Code Playgroud)

2)toCanIsTruthyOps隐式转换方法在评估时在范围内10.truthy,因此编译器在看到Int没有方法时会尝试使用这种隐式转换truthy方法.因此编译器将尝试寻找一些隐式转换方法,该方法转换10为具有方法的对象,truthy因此它将尝试toCanIsTruthyOps进行此转换.

3)我怀疑intCanTruthy当编译器尝试toCanIsTruthyOps隐式转换时,可能会以某种方式使用隐式值10.

但这是我真正迷失的地方.我只是没有看到隐含的解决方法过程如何进行.接下来发生什么 ?怎么样,为什么?

换句话说,我不知道什么是允许编译器truthy在评估时找到方法实现的隐式解析序列10.truthy.

问题:

如何10转换为具有正确truthy方法的某个对象?

那个对象是什么?

那个对象来自哪里?

有人可以详细解释在评估时如何进行隐式解决方案10.truthy吗?

自我类型 如何 在隐式解决过程{ 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
Run Code Online (Sandbox Code Playgroud)

尝试使用类型类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
Run Code Online (Sandbox Code Playgroud)

0__*_*0__ 5

首先,感谢您粘贴一个完全独立的示例.

如何10转换为具有正确truthy方法的某个对象?

在类型A不提供该方法的值上调用方法时,必须启动隐式转换,即必须在范围内A => B使用B具有问题(truthy)方法的签名的方法或函数.在转换方法的情况下,它可能要求额外的隐含参数,这些参数将被相应地查找.

转换方法是toCanIsTruthyOps通过导入的内容提供的ToCanIsTruthyOps.B那么上述句子中的类型是CanTruthyOps,转换方法是toCanIsTruthyOps.只要CanTruthy找到隐式类型类证据参数,编译器就可以调用它.因此type A = Int,CanTruthy[Int]如果调用10.truthy成功,编译器必须找到类型的隐式值.

它在几个地方寻找这样的价值.它可能位于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
Run Code Online (Sandbox Code Playgroud)

自我类型如何在隐式解决过程{ self => ...CanTruthy发挥作用?

它与隐式解决方案无关.实际上,在你的例子中trait CanTruthy,self作为别名的行为this甚至没有被使用,所以你可以删除它.