构建三层深度 F-Bound 类型
Constructing three level deep F-Bound types
我有三种 F-Bound 类型 A
、B
和 C
,其中 B
由 A
参数化,C
由 B
参数化(因此也由 A
参数化)。我可以实例化 A
和 B
,但是当我尝试实例化 C
时,编译器无法推断类型。如果我明确地给它类型,一切正常 - 但这些类型丢失似乎很愚蠢(这是由于类型擦除吗?)。
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,但是切换到抽象类型成员可以解决这个问题吗? class 会是什么样子?
怎么样:
... //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]
只是将 BB
提升为 B[BInst[AInst], AInst]
。
P.S。对于类型成员,您仍然以某种方式推动将类型传递给您的案例 类,所以没有太大区别。
我有三种 F-Bound 类型 A
、B
和 C
,其中 B
由 A
参数化,C
由 B
参数化(因此也由 A
参数化)。我可以实例化 A
和 B
,但是当我尝试实例化 C
时,编译器无法推断类型。如果我明确地给它类型,一切正常 - 但这些类型丢失似乎很愚蠢(这是由于类型擦除吗?)。
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,但是切换到抽象类型成员可以解决这个问题吗? class 会是什么样子?
怎么样:
... //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]
只是将 BB
提升为 B[BInst[AInst], AInst]
。
P.S。对于类型成员,您仍然以某种方式推动将类型传递给您的案例 类,所以没有太大区别。