2

次のようなポリモーフィックな特性が与えられた場合

 trait Transform[T] { def apply( t: T ) : T }

次のようなさまざまな特殊なインスタンスを実装したい場合があります。

 case class Add[Double] extends Transform[Double] { def apply( t: Double ) ... }
 case class Append[String] extends Transform[String] { def apply( t: String ) ... }

など。現在、頻繁に必要とされる変換は恒等変換でもあります。型 T ごとに ID を特殊化する代わりに、すべての型 T に対して単一のインスタンスを 1 つだけ使用する方が望ましいようです。私の質問は、Scala でこれを実現する最善の方法は何ですか?

ここに私が見つけたものがあります: List[T] が List.empty[T] と Nil を実装する方法を見て、私は Nothing を型 T として使用してみました. Nothing は他のすべての型のサブタイプであるため、これは理にかなっているようです:

 object Identity extends Transform[Nothing] {
    def apply( t: Nothing ) = t
 }

これはうまくいくようです。ただし、このインスタンスをそのまま使用したい場合は、次のようにします。

 val array = Array[Transform[String]]( Transform.Identity )

「タイプの不一致; 検出: Identity.type, 必須: Transform[String]」というコンパイラ エラーが発生します。それを使用するには、明示的にキャストする必要があります。

 ... Identity.asInstanceOf[Transform[String]]

これが最善の方法であるか、それとも「適切な」方法であるかはわかりません。アドバイスをありがとう。

4

2 に答える 2

5

@Kim Stebel が指摘しているように、あなたTransform[T]は invariant ですT(そしてT、co-variant と contra-variant の両方の位置で発生するため、def apply(t : T) : T)そうTransform[Nothing]Transform[String]なければなりません。

あなたの主な関心事がキムの各呼び出しでのインスタンスの作成である場合def Id[A]、最良のモデルは in のconformsin Predefの定義です。

private[this] final val singleton_<:< = new <:<[Any,Any] { def apply(x: Any): Any = x }
implicit def conforms[A]: A <:< A = singleton_<:<.asInstanceOf[A <:< A]

すなわち。ポリモーフィック メソッドを使用して、適切な型にキャストされたシングルトン値を返します。これは、消去が勝利する機会の 1 つです。

あなたの状況に当てはめると、

object SingletonId extends Transform[Any] { def apply(t : Any) = t }
def Id[A] = SingletonId.asInstanceOf[Transform[A]]

サンプルREPLセッション、

scala> Id("foo")
res0: java.lang.String = foo

scala> Id(23)
res1: Int = 23
于 2011-10-03T08:38:43.647 に答える
4

の型パラメータTTransform[T]不変でTransform[Nothing]あり、のサブタイプではないTransform[String]ため、コンパイラはそれについて文句を言います。ただしNothing、のインスタンスは存在しないため、ここで使用しても意味がありませんNothing。では、どのようにメソッドに渡すのでしょうapplyか?もう一度キャストする必要があります。私が見ることができる唯一のオプションはこれです:

scala> def Id[A] = new Transform[A] { override def apply(t:A) = t }
Id: [A]=> java.lang.Object with Transform[A]

scala> Id(4)
res0: Int = 4

scala> Id("")
res1: java.lang.String = ""
于 2011-10-03T06:16:04.617 に答える