问题描述
我正在设计F-Bound数据类型,并且有一个正常工作的伴随对象.我想从特征本身中引用此伴侣对象,但我无法正确选择类型.
I am designing a F-Bound data type, and have a working companion object. I would like to reference this companion object from the trait itself, but I can't get the types right.
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
的可行解决方案就足够了.
A working solution for either companion
or companion2
would suffice, although a general hint on how to construct these type signatures would be useful.
修改
我想使用随播对象来存储canBuildFrom
样式隐式对象和Builders,但是由于内容类型A
具有上限,因此所有生成函数都需要了解此边界,因此参数化伴随对象特征的特征.此设计的灵感来自 GenericCompanion.scala ,当然,添加类型界限会使一切变得更加困难:P
I want to use the companion object to store canBuildFrom
style implicits as well as Builders, but as the content type A
has an upper bound, all generating functions need to be aware of this bounding, so hence the parametrization of the companion object trait. The inspiration for this design comes from GenericCompanion.scala, of course, adding the type bounds makes everything more difficult :P
推荐答案
companion
类型的任何明确定义的障碍是BComp
由两个 parametriczed 类型进行了参数设置-而第一个与B
兼容,第二个AA[Y <: AA[Y]]
无法构建.很简单,我们需要将此类型添加到B
的参数化中:
The obstacle to any clear definition of types for companion
is that BComp
is parametrized by two parametrized types - while the first one is compatible with B
, the second one AA[Y <: AA[Y]]
is impossible to construct. So quite simply, we need to add this type to the parametrization of 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
(只需要很小的扩展):
now we have a compatible type AA
for our companion object (which needs only a small expansion):
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
对于companion2
,我们只需要更改B
的参数化的第一部分,以使特征B
和伴随特征变为:
For companion2
, we just need to change the first part of the parametrization of B
, so that trait B
and the companion trait become:
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]]]
这稍微易于管理.案例类和案例对象为:
This is slightly more manageable. The case class and case objects are:
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]
如果这对任何人都有用,请重新考虑.我已经更改了自己的设计方法,建议您也这样做.提出针对这些类型的解决方案现在纯粹是一项学术工作!
If this is useful to anybody the rethink. I have changed my own design approach and I suggest you do too. Coming up with a solution to these types has now been a purely academic exercise!
这篇关于scala:使用F绑定参数引用特性的文章就介绍到这了,希望我们推荐的答案对大家有所帮助,也希望大家多多支持!