简体   繁体   English

scala:使用F绑定参数引用特性

[英]scala: Referencing Trait with F-Bound Parameters

I am designing a F-Bound data type, and have a working companion object. 我正在设计一个F-Bound数据类型,并具有一个正常工作的伴随对象。 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]

A working solution for either companion or companion2 would suffice, although a general hint on how to construct these type signatures would be useful. 尽管对于如何构造这些类型签名的一般提示将很有用,但是可以为companioncompanion2提供一个companion解决方案。

edit 编辑

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. 我想使用随canBuildFrom对象来存储canBuildFrom样式隐式对象以及Builders,但是由于内容类型A具有上限,所有生成函数都需要意识到这一边界,因此,对随播对象特征进行参数化。 The inspiration for this design comes from GenericCompanion.scala , of course, adding the type bounds makes everything more difficult :P 这种设计的灵感来自GenericCompanion.scala ,当然,添加类型边界会使一切变得更加困难:P

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. 不能明确定义companion类型的障碍是BComp由两种参数化类型进行了参数化 -第一种与B兼容,而第二种AA[Y <: AA[Y]]无法构造。 So quite simply, we need to add this type to the parametrization of B : 很简单,我们需要将此类型添加到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]
}

now we have a compatible type AA for our companion object (which needs only a small expansion): 现在,我们为伴随对象提供了兼容的AA类型(只需要进行小扩展):

trait BComp[BHere[BB <: BHere[BB, AAA, Z],
                  AAA[Y <: AAA[Y]],
                  Z <: AAA[Z]],
            AA[Y <: AA[Y]]]

Isn't that pretty? 那不是很漂亮吗?

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

For companion2 , we just need to change the first part of the parametrization of B , so that trait B and the companion trait become: 对于companion2 ,我们只需要更改B的参数化的第一部分,以使特征B和伴随特征变为:

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! 提出针对这些类型的解决方案现在纯粹是一项学术工作!

声明:本站的技术帖子网页,遵循CC BY-SA 4.0协议,如果您需要转载,请注明本站网址或者原文地址。任何问题请咨询:yoyou2525@163.com.

 
粤ICP备18138465号  © 2020-2024 STACKOOM.COM