Scala:双 F 有界多态类型的伴随对象
Scala: Companion objects for doubly F-Bounded Polymorphic types
我有一个 F-Bound 类型:
sealed trait A[AA <: A[AA]] {
self: AA =>
}
还有第二种 F-Bound 类型,由第一种类型参数化。
sealed trait B[BB <: B[BB, AA], AA <: A[AA]] {
self: BB =>
val content: AA
}
我可以愉快地编写使用这些类型的案例 classes:
case class BInst[BB <: BInst[BB, AA], AA <: A[AA]](content: AA)
extends B[BInst[BB, AA], AA]
现在我想要一个案例 class 的伴随对象,我可以通过特征 B 引用它,例如:
sealed trait A[AA <: A[AA]] { self: AA => }
sealed trait B[BB <: B[BB, AA], AA <: A[AA]] {
self: BB =>
val content: AA
def companion: Companion[BB]
}
case class BInst[BB <: BInst[BB, AA], AA <: A[AA]](content: AA)
extends B[BInst[BB, AA], AA] {
def companion: Companion[BInst[BB, AA]] = BInst
}
sealed trait Companion[+BB <: B[_, _]]
object BInst extends Companion[BInst]
但这无法编译,因为伴随参数化(最后一行)中的 BInst 需要类型参数。
同样
sealed trait Companion[BB[X, Y] <: B[X, Y]]
失败。伴生对象的正确类型是什么?
我看到的唯一方法是放弃 Companion
/BInst
的通用参数,因为即使从类型角度来看也可能只有一个对象实例(只有一个 BInst.type
类型) :
scala> sealed trait A[AA <: A[AA]] { self: AA => }
sealed trait B[BB <: B[BB, AA], AA <: A[AA]] {
self: BB =>
val content: AA
def companion: Companion[_]
}
case class BInst[BB <: BInst[BB, AA], AA <: A[AA]](content: AA)
extends B[BInst[BB, AA], AA] {
def companion = BInst
}
sealed trait Companion[+BB <: B[_, _]]
object BInst extends Companion[BInst[_, _]]
defined trait A
defined trait B
defined class BInst
defined trait Companion
defined module BInst
之后你可以实际施放你的 BInst
(在 class 内):
def companion: Companion[BInst[BB, AA]] =
BInst.asInstanceOf[Companion[BInst[BB, AA]]
如果你不在你的 Companion
-trait/BInst
-object 中转换类型(最好只使用 BB
/AA
-独立的方法BInst
class) 没有获取 ClassCastException 的风险,.asInstanceOf[Companion[BInst[BB, AA]]]
只会为您创建(克隆)新类型,使用 BInst
作为原型。
我已尝试将您在此处所写的内容与您的其他问题合并:
通过保持代码的可编译性,我可以尽可能地接近您的代码:
import scala.language.higherKinds
trait A[AA <: A[AA]] { self: AA => }
trait B[
X <: A[X],
This[Y <: A[Y]] <: B[Y, This]
] {
self: This[X] =>
def content: X
def companion: Companion[This]
}
trait Companion[Coll[X <: A[X]] <: B[X, Coll]]
case class BInst[X <: A[X]](content: X)
extends B[X, BInst] {
def companion: Companion[BInst] = BInst
}
object BInst extends Companion[BInst]
您的 BB
已被 This
替换,参数顺序已交换,因此它与标准集合库中的做法更相似。
一般性评论。
您似乎不太确定您想要从 BInst
和 BComp
/Companion
得到什么。它是您问题的两个版本,它们似乎具有完全不同的类型。如果您不太确定自己想要什么,建议尽可能简单。有轶事证据表明 all these F-Bound-GenericCompanionCanBuildFromFactories can be difficult to get right.
我有一个 F-Bound 类型:
sealed trait A[AA <: A[AA]] {
self: AA =>
}
还有第二种 F-Bound 类型,由第一种类型参数化。
sealed trait B[BB <: B[BB, AA], AA <: A[AA]] {
self: BB =>
val content: AA
}
我可以愉快地编写使用这些类型的案例 classes:
case class BInst[BB <: BInst[BB, AA], AA <: A[AA]](content: AA)
extends B[BInst[BB, AA], AA]
现在我想要一个案例 class 的伴随对象,我可以通过特征 B 引用它,例如:
sealed trait A[AA <: A[AA]] { self: AA => }
sealed trait B[BB <: B[BB, AA], AA <: A[AA]] {
self: BB =>
val content: AA
def companion: Companion[BB]
}
case class BInst[BB <: BInst[BB, AA], AA <: A[AA]](content: AA)
extends B[BInst[BB, AA], AA] {
def companion: Companion[BInst[BB, AA]] = BInst
}
sealed trait Companion[+BB <: B[_, _]]
object BInst extends Companion[BInst]
但这无法编译,因为伴随参数化(最后一行)中的 BInst 需要类型参数。 同样
sealed trait Companion[BB[X, Y] <: B[X, Y]]
失败。伴生对象的正确类型是什么?
我看到的唯一方法是放弃 Companion
/BInst
的通用参数,因为即使从类型角度来看也可能只有一个对象实例(只有一个 BInst.type
类型) :
scala> sealed trait A[AA <: A[AA]] { self: AA => }
sealed trait B[BB <: B[BB, AA], AA <: A[AA]] {
self: BB =>
val content: AA
def companion: Companion[_]
}
case class BInst[BB <: BInst[BB, AA], AA <: A[AA]](content: AA)
extends B[BInst[BB, AA], AA] {
def companion = BInst
}
sealed trait Companion[+BB <: B[_, _]]
object BInst extends Companion[BInst[_, _]]
defined trait A
defined trait B
defined class BInst
defined trait Companion
defined module BInst
之后你可以实际施放你的 BInst
(在 class 内):
def companion: Companion[BInst[BB, AA]] =
BInst.asInstanceOf[Companion[BInst[BB, AA]]
如果你不在你的 Companion
-trait/BInst
-object 中转换类型(最好只使用 BB
/AA
-独立的方法BInst
class) 没有获取 ClassCastException 的风险,.asInstanceOf[Companion[BInst[BB, AA]]]
只会为您创建(克隆)新类型,使用 BInst
作为原型。
我已尝试将您在此处所写的内容与您的其他问题合并:
通过保持代码的可编译性,我可以尽可能地接近您的代码:
import scala.language.higherKinds
trait A[AA <: A[AA]] { self: AA => }
trait B[
X <: A[X],
This[Y <: A[Y]] <: B[Y, This]
] {
self: This[X] =>
def content: X
def companion: Companion[This]
}
trait Companion[Coll[X <: A[X]] <: B[X, Coll]]
case class BInst[X <: A[X]](content: X)
extends B[X, BInst] {
def companion: Companion[BInst] = BInst
}
object BInst extends Companion[BInst]
您的 BB
已被 This
替换,参数顺序已交换,因此它与标准集合库中的做法更相似。
一般性评论。
您似乎不太确定您想要从 BInst
和 BComp
/Companion
得到什么。它是您问题的两个版本,它们似乎具有完全不同的类型。如果您不太确定自己想要什么,建议尽可能简单。有轶事证据表明 all these F-Bound-GenericCompanionCanBuildFromFactories can be difficult to get right.