4

こんにちは、高度な Scala の本を読んでいますが、scalaz ソースからのこのコードを理解するのに苦労しています。

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])に変換できますか?

助けてくれてありがとう。

4

1 に答える 1

12

これは消去のために機能します。@@は純粋に型レベルの構造であり、実行時の表現を持たないことを意味します。

typeA @@ Tは type のエイリアスですAnyRef{type Tag = T; type Self = A}。そしてInt安全にキャストできるので(内部的には aを a にAnyRefキャストすることで行われます)、これは問題なく動作します。java.lang.Integerjava.lang.Object

追加の構造{type Tag = T; type Self = A}はコンパイル時にのみ存在するため、JVM がキャストを実行するまでに完全に消去されています。

なぜこれを行うのですか?(私は「qua」と発音します)の目的は@@、実行時のオーバーヘッドを招くことなく、古い型から新しい型を作成することです。

たとえば を使用した場合、これによりとは異なるものとしてcase class Multiplication(value: Int)扱うことができますが、実行時に実際のオブジェクトが作成されます。MultiplicationIntMultiplication

のような型エイリアスを使用した場合type Multiplication = Int、実行時のオーバーヘッドはありません。しかし、現在Multiplicationは と区別がつかずInt、これは私たちが望んでいるものではありません。

型は、実際には実行時の であってもInt @@ Multiplication、この型の値を として直接使用することを防ぎます。IntInt

于 2015-05-03T13:58:05.973 に答える