Scala中抽象类型的F-有界多态性
我读过几篇文章,表达了应该使用抽象类型来实现Scala中的f-有界多态性。这主要是为了缓解类型推断问题,但也为了消除类型参数在定义递归类型时似乎引入的二次增长 这些定义如下:Scala中抽象类型的F-有界多态性,scala,generics,polymorphism,scala-2.10,Scala,Generics,Polymorphism,Scala 2.10,我读过几篇文章,表达了应该使用抽象类型来实现Scala中的f-有界多态性。这主要是为了缓解类型推断问题,但也为了消除类型参数在定义递归类型时似乎引入的二次增长 这些定义如下: trait EventSourced[E] { self => type FBound <: EventSourced[E] { type FBound <: self.FBound } def apply(event: E): FBound } 2) 编译器现在无法推断上述方法的类型参
trait EventSourced[E] {
self =>
type FBound <: EventSourced[E] { type FBound <: self.FBound }
def apply(event: E): FBound
}
2) 编译器现在无法推断上述方法的类型参数,失败消息为:
Type mismatch, expected: NotInferredES#FBound, actual: MyImpl#FBound
有没有人在他们的解决方案中成功地实现了f-有界多态性,从而编译器仍然能够推断类型?请参阅的讨论。我可能在以下实现中遗漏了一些东西
trait EventSourced[E] {
self =>
type FBound <: EventSourced[E] { type FBound <: self.FBound }
def apply(event: E): FBound
}
trait Something[ES, E]
def mapToSomething[E](
eventSourced: ES forSome {
type ES <: EventSourced[E]
}): Something[eventSourced.type, E] = ???
class Test extends EventSourced[Boolean] {
type FBound = Test
def apply(event:Boolean):FBound = ???
}
val x:Test = ???
mapToSomething(x)
trait事件源[E]{
自我=>
类型FBound我后来意识到在大多数情况下应该避免f-限制多态性-或者更确切地说-通常有一种可供选择的设计。要了解如何避免它,我们首先需要知道是什么让我们需要它:
当类型期望在派生类型中引入重要的接口更改时,就会发生F-有界多态性
通过组合预期的更改区域而不是试图通过继承来支持它们,可以避免这种情况。这实际上又回到了“四人帮”设计模式:
支持“对象组合”而不是“类继承”
--(四人帮,1995年)
例如:
trait Vehicle[V <: Vehicle[V, W], W] {
def replaceWheels(wheels: W): V
}
这里,“预期变化”是指车辆类型(例如自行车
,汽车
,卡车
).前面的示例假设这将通过继承添加,需要一个f-有界类型,使得任何使用Vehicle的函数都无法推断W
。使用合成的新方法不会出现此问题
请参阅:Scala collections库成功地使用了F-bounded多态性,没有任何问题。它使用类型参数而不是类型成员,您可能希望尝试基于此的解决方案。请给我一个示例,例如,库的哪些部分可以这样做?请参阅标准库中的。请注意使用的F-bounded多态性在继承GenericTraversableTemplate和LinearSeqOptimized的过程中。谢谢,我将在这里调查Martin对f-有界多态性的使用,看看编译器是否存在与我的代码使用类型参数时相同的类型推断问题:DCan你能告诉我们你希望这段代码做什么吗?mapToSomething应该做什么eturn?此示例使用类型参数,因此会导致推断问题。在我的示例中,无法在调用站点推断以下方法定义的类型:def doSomething[ES在Twitter或Scala库的示例中,F-bound类型参数在类本身上,而不是在方法上。F-bounded多态性允许方法引用this
的类型,即它最终在子类中的确切类型。例如TraversableLike
中继承的map
的定义List
,defmap[B,That](f:A=>B)(隐式bf:CanBuildFrom[Repr,B,That]):That
。Repr是f-Bound类型参数,是List[A]在列表内部,但是TraversableLike中的代码可以在不了解<代码>列表的情况下编写。是的,我认为最终我需要重新考虑我的一些设计。在我看来,当从f-有界超类型继承时,f-有界多态性应该只在类型定义级别使用。然而,在我的代码中,有几个实例在方法级别使用它的地方…我觉得这需要改变。我遵循了链接,但是只有类型参数实现,没有关于f-bound的抽象类型实现的任何提示polymorphism@ayvango抽象的内部类型和类型参数在Scala中是等价的使用抽象类型编写一个示例。>使用组合的新方法不会显示此问题,这并不完全正确。如果您希望保留类型级别检查,您最终将需要它,如VehicleType[V]
trait Vehicle[V <: Vehicle[V, W], W] {
def replaceWheels(wheels: W): V
}
trait Vehicle[T, W] {
val vehicleType: T
def replaceWheels(wheels: W): Vehicle[T, W]
}