[英]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.