scala:使用 F 绑定参数引用特征
scala: Referencing Trait with F-Bound Parameters
我正在设计一个 F-Bound 数据类型,并且有一个工作伙伴对象。我想从特征本身引用这个伴生对象,但我无法获得正确的类型。
trait A[AA <: A[AA]] {
self =>
val data: String
}
case class A1(data : String) extends A[A1]
trait B[BB <: B[BB, AA], AA <: A[AA]] {
self: BB =>
val content: AA
def companion: BComp[BB, AA] // What is the correct type?
def companion2: BComp2[BB, AA] // What is the correct type?
}
trait BComp[BB[X <: BB[X, AA], Y <: AA[Y]], AA[Y <: AA[Y]]]
trait BComp2[BB[X <: AA[X]], AA[X <: AA[X]]]
case class BInst[AA <: A[AA]](content: AA) extends B[BInst[AA], AA] {
def companion = BInst
def companion2 = BInst2
}
object BInst extends BComp[B, A]
object BInst2 extends BComp2[BInst, A]
companion
或 companion2
的工作解决方案就足够了,尽管关于如何构建这些类型签名的一般提示会很有用。
编辑
我想使用伴随对象来存储 canBuildFrom
样式隐式以及构建器,但是由于内容类型 A
有上限,所有生成函数都需要知道这一点边界,因此伴随对象特征的参数化。这个设计的灵感来自于GenericCompanion.scala,当然,加上type bounds就更难了:P
companion
类型的任何明确定义的障碍是 BComp
由两个 参数化 类型参数化 - 而第一个兼容B
,第二个AA[Y <: AA[Y]]
无法构造。所以很简单,我们需要将此类型添加到 B
:
的参数化中
trait B[BB <: B[BB, AA, X],
AA[T <: AA[T]] <: A[T],
X <: AA[X]] {
self: BB =>
val content: X
def companion: BComp[B, AA]
}
现在我们有一个兼容类型 AA
用于我们的伴随对象(只需要一个小的扩展):
trait BComp[BHere[BB <: BHere[BB, AAA, Z],
AAA[Y <: AAA[Y]],
Z <: AAA[Z]],
AA[Y <: AA[Y]]]
是不是很漂亮?
case class BInst[X <: A[X]](content: X) extends B[BInst[X], A, X] {
def companion: BComp[B, A] = BInst5
}
object BInst extends BComp[B, A]
companion2
对于companion2
,我们只需要改变B
参数化的第一部分,这样trait B
和companion trait就变成了:
trait B[BB[TS <: AA[TS]] <: B[BB, AA, TS],
AA[T <: AA[T]] <: A[T],
X <: AA[X]] {
self: BB[X] =>
val content: X
def companion2: BComp[BB, AA]
}
trait BComp[BHere[TS <: AA[TS]],
AA[Y <: AA[Y]]]
这稍微更易于管理。案例 class 和案例对象是:
case class BInst[X <: A[X]](content: X) extends B[BInst, A, X] {
def companion2: BComp[BInst, A] = BInst5
}
object BInst extends BComp[BInst, A]
如果这对任何人有用,请重新考虑。我已经改变了我自己的设计方法,我建议你也这样做。为这些类型提出解决方案现在已经成为纯粹的学术练习!
我正在设计一个 F-Bound 数据类型,并且有一个工作伙伴对象。我想从特征本身引用这个伴生对象,但我无法获得正确的类型。
trait A[AA <: A[AA]] {
self =>
val data: String
}
case class A1(data : String) extends A[A1]
trait B[BB <: B[BB, AA], AA <: A[AA]] {
self: BB =>
val content: AA
def companion: BComp[BB, AA] // What is the correct type?
def companion2: BComp2[BB, AA] // What is the correct type?
}
trait BComp[BB[X <: BB[X, AA], Y <: AA[Y]], AA[Y <: AA[Y]]]
trait BComp2[BB[X <: AA[X]], AA[X <: AA[X]]]
case class BInst[AA <: A[AA]](content: AA) extends B[BInst[AA], AA] {
def companion = BInst
def companion2 = BInst2
}
object BInst extends BComp[B, A]
object BInst2 extends BComp2[BInst, A]
companion
或 companion2
的工作解决方案就足够了,尽管关于如何构建这些类型签名的一般提示会很有用。
编辑
我想使用伴随对象来存储 canBuildFrom
样式隐式以及构建器,但是由于内容类型 A
有上限,所有生成函数都需要知道这一点边界,因此伴随对象特征的参数化。这个设计的灵感来自于GenericCompanion.scala,当然,加上type bounds就更难了:P
companion
类型的任何明确定义的障碍是 BComp
由两个 参数化 类型参数化 - 而第一个兼容B
,第二个AA[Y <: AA[Y]]
无法构造。所以很简单,我们需要将此类型添加到 B
:
trait B[BB <: B[BB, AA, X],
AA[T <: AA[T]] <: A[T],
X <: AA[X]] {
self: BB =>
val content: X
def companion: BComp[B, AA]
}
现在我们有一个兼容类型 AA
用于我们的伴随对象(只需要一个小的扩展):
trait BComp[BHere[BB <: BHere[BB, AAA, Z],
AAA[Y <: AAA[Y]],
Z <: AAA[Z]],
AA[Y <: AA[Y]]]
是不是很漂亮?
case class BInst[X <: A[X]](content: X) extends B[BInst[X], A, X] {
def companion: BComp[B, A] = BInst5
}
object BInst extends BComp[B, A]
companion2
对于companion2
,我们只需要改变B
参数化的第一部分,这样trait B
和companion trait就变成了:
trait B[BB[TS <: AA[TS]] <: B[BB, AA, TS],
AA[T <: AA[T]] <: A[T],
X <: AA[X]] {
self: BB[X] =>
val content: X
def companion2: BComp[BB, AA]
}
trait BComp[BHere[TS <: AA[TS]],
AA[Y <: AA[Y]]]
这稍微更易于管理。案例 class 和案例对象是:
case class BInst[X <: A[X]](content: X) extends B[BInst, A, X] {
def companion2: BComp[BInst, A] = BInst5
}
object BInst extends BComp[BInst, A]
如果这对任何人有用,请重新考虑。我已经改变了我自己的设计方法,我建议你也这样做。为这些类型提出解决方案现在已经成为纯粹的学术练习!