2015-05-03 40 views
4

您好我正在學習高級斯卡拉的書,我有一些麻煩,從scalaz源understading這段代碼:Scalaz`Tag.apply`:它是如何工作的?

object Tag { 
    /** `subst` specialized to `Id`. 
    * 
    * @todo According to Miles, @specialized doesn't help here. Maybe manually specialize. 
    */ 
    @inline def apply[@specialized A, T](a: A): A @@ T = a.asInstanceOf[A @@ T] 

    // ... 
} 

它如何工作? a.asInstanceOf[A @@ T]應該失敗,ClassCastException不應該嗎?

用法的例子是:

Multiplication(2) |+| Multiplication(3) 

在這種情況下是a一個Int怎麼能轉換爲@@[Int, Multiplication]Tagged[Int, Multiplication]

感謝您的幫助。

+0

什麼是「高級Scala書」?我在Google上沒有找到任何這樣的書。 –

+1

這是從下劃線書:http://underscore.io/training/courses/advanced-scala-scalaz –

回答

12

這是因爲擦除@@是純粹的類型級別的構造,意味着它沒有運行時表示。

類型A @@ TAnyRef{type Tag = T; type Self = A}類型的別名。並且由於Int可以安全地投射到AnyRef(在引擎蓋下,這是通過將java.lang.Integer投射到java.lang.Object來完成的),這工作得很好。

附加結構{type Tag = T; type Self = A}只存在於編譯時,所以在JVM執行轉換時它已被完全擦除。

爲什麼這樣做? @@(我發音爲「qua」)的目的是從舊版本創建一個新類型,而不會產生運行時間開銷。

如果我們使用,例如,case class Multiplication(value: Int),這使我們能夠把Multiplication區別於Int,但它在運行時創建一個實際Multiplication對象。

如果我們使用類型別名如type Multiplication = Int,那麼沒有運行時間開銷。但是現在MultiplicationInt沒有區別,這不是我們想要的。

類型Int @@ Multiplication阻止我們直接使用這種類型的值作爲Int,儘管它在運行時確實只是一個Int

+0

現在感謝它是有道理的。它基本上是Scala 2.10之前的一個值類。 –

+0

這比value類嚴格得多,因爲'A @@ T'中的類型'A'可以是任何類型的,不只是值類中的AnyVal的子類型。 – Apocalisp

+0

哦,對,謝謝! –

相關問題