2

私は 3 つの F-Bound タイプAB&Cを持ってBいます。とをインスタンス化できますが、 をインスタンス化しようとすると、コンパイラは型を推測できません。明示的に型を指定すると、すべてが機能しますが、これらの型が失われるのはかなりばかげているようです (これは型の消去によるものですか?)。ACBAABC

sealed trait A[AA <: A[AA]] {
  self =>
  val data: String
}

case class AInst(data: String) extends A[AInst]

sealed trait B[BB <: B[BB, AA], AA <: A[AA]] {
  self: BB =>
  val content: AA
}

case class BInst[AA <: A[AA]](content: AA) extends B[BInst[AA], AA]

sealed trait C[CC <: C[CC, BB, AA], BB <: B[BB, AA], AA <: A[AA]] {
  self: CC =>
  val content: BB
}

case class CInst[BB <: B[BB, AA], AA <: A[AA]](content: BB) 
     extends C[CInst[BB, AA], BB, AA]

val a1 = new AInst("A1")
val b1 = BInst(a1)
val c1 = CInst[BInst[AInst],AInst](b1)

具体的に型を指定する必要がない回避策はありますCInstか?

現在、型のパラメーター化を使用して F-Bounds を実装していますが、抽象型メンバーに切り替えるとこの問題は解決しますか? その時、クラスはどのようになりますか?

4

1 に答える 1

1

どのようにそのことについて:

... //A,AInst,B,BInst without changes

sealed trait C[CC <: C[CC, BB, AA], BB <: B[BB, AA], AA <: A[AA]] {
  self: CC =>
  val content: B[BB, AA] //`B[BB, AA]` instead of `BB`
}

case class CInst[BB <: B[BB, AA], AA <: A[AA]](content: B[BB,AA]) extends C[CInst[BB, AA], BB, AA]

使用法:

scala> val a1 = new AInst("A1")
a1: AInst = AInst(A1)

scala> val b1 = BInst(a1)
b1: BInst[AInst] = BInst(AInst(A1))

scala> val c1 = CInst(b1)
c1: CInst[BInst[AInst],AInst] = CInst(BInst(AInst(A1)))

以前はコンパイラが のように見えなかったBBのでBInst[AA <: A[AA]]、.B[BB,AA]BBB[BInst[AInst], AInst]

PSタイプメンバーを使用すると、何らかの方法でタイプをケースクラスに渡すようにプッシュしたため、大きな違いはありません。

于 2015-04-16T12:40:59.500 に答える