繁体   English   中英

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

[英]What is the implicit resolution sequence in this “simple” ScalaZ tutorial code example?

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

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

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

1)隐含值intCanTruthyCanTruthy[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.truthytoCanIsTruthyOps隐式转换方法在范围内,因此当编译器看到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实例将被查找并作为CanTruthyOpsF属性存储起来:

implicit def F: CanTruthy[A] = ev

(实际上我不知道为什么implicit在那里是必要的; truthy()将明确转向F

F.truthys(self)

至于隐式解析是如何工作的,最好还是查找详细描述该过程的文档。

暂无
暂无

声明:本站的技术帖子网页,遵循CC BY-SA 4.0协议,如果您需要转载,请注明本站网址或者原文地址。任何问题请咨询:yoyou2525@163.com.

 
粤ICP备18138465号  © 2020-2024 STACKOOM.COM