1

私はより多くの Scala を学ぼうとしており、F-bounded 型について説明しているこの興味深い記事に出くわしました。そのような型を持つ値のコレクションの操作に関する最後の議論に特に興味がありました。

簡単な例を次に示します。

abstract class AbsClass[A <: AbsClass[_]] {
  this: A =>
  def me: A = this
}

def me2[A <: AbsClass[A]](a: A): A = a

case class C1(v: Int) extends AbsClass[C1] 
case class C2(v: Int) extends AbsClass[C2] 

ブログ投稿に示されているように、存在量指定子を使用して、 と のリストを呼び出すことができますme2C1C2

scala> List[A forSome {type A <: AbsClass[A] }](C1(1), C2(2)).map(me2(_))
res2: List[A forSome { type A <: AbsClass[A] }] = List(C1(1), C2(2))

今、私はリストのタイプについていくつかのバリエーションを試してきました。経験豊富な誰かが、私が見逃している微妙な点を指摘してくれることを期待していました。

以下は期待どおりに機能します

scala> val l2  =  List[A forSome {type A <: AbsClass[A] }](C1(1), C2(2))
l2: List[A forSome { type A <: AbsClass[A] }] = List(C1(1), C2(2))

scala> l2.map(_.me)
res4: List[A forSome { type A <: AbsClass[A] }] = List(C1(1), C2(2))

次のように、_.meのインスタンスを含むリストを呼び出して示すこともできます。AbsClass[A] forSome {type A}

scala> val l: List[AbsClass[_]] = List(C1(1), C2(2)).map(_.me)
l: List[AbsClass[_]] = List(C1(1), C2(2))

しかし、同じマップをlもう一度適用しようとすると、型情報が失われ、List[Any]. ここで型を維持する方法はありますか?

4

1 に答える 1

1

アンダースコアはタイプ バインドであることに注意してください。

val l: List[AbsClass[_]] = List(C1(1), C2(2)).map(_.me)

val ll: List[AbsClass[_ >: Nothing <: Any]] = List(C1(1), C2(2)).map(_.me)

これら 2 つのことは同じです。アンダースコアは、Nothing の下限または Any の上限のいずれかに押しつぶされます。

存在型の仕組みの詳細については、https ://youtu.be/NFnsFda82Yo を参照してください。

于 2016-07-05T04:33:54.457 に答える