Below is a snippet of code from this ScalaZ tutorial.
I cannot understand how implicit resolution rules are applied when evaluating 10.truthythe bottom of the sample code.
Things that I think I understand are as follows:
1) An implicit value intCanTruthyis an instance of an anonymous subclass CanTruthy[A]that defines a method truthysfor Int-s according to:
scala> implicit val intCanTruthy: CanTruthy[Int] = CanTruthy.truthys({
case 0 => false
case _ => true
})
intCanTruthy: CanTruthy[Int] = CanTruthy$$anon$1@71780051
2) The implicit conversion method toCanIsTruthyOpsis in scope during evaluation 10.truthy, so the compiler will try to use this implicit conversion method when it sees that it Intdoes not have a method truthy. Thus, the compiler will try to find some kind of implicit conversion method that will convert 10to an object that has a method truthy, and therefore it will try to toCanIsTruthyOpsconvert that.
3) I suspect that the implicit value intCanTruthycan be used in some way when the compiler tries to implicitly convert toCanIsTruthyOpsto 10.
But here I really got lost. I just don’t see how the process of implicit resolution occurs after this. What will happen next? How and why?
, , , truthy 10.truthy.
10 - , truthy?
?
?
- , , 10.truthy?
self-type { 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