我一直在考虑我正在处理的库中的设计问题,并且我意识到使用存在类型可能允许我以简化库的许多部分的方式更改我的设计。但是,我似乎无法让它发挥作用。
在我看来myBuilder
符合MultiSignalBuilder[E, R] forSome { type E[+X] >: Element[X] }
类型,其中Element[X]
是MultiSignalElement[X]
,但编译器说它确实是 class MultiSignalElement[+T] {
}
abstract class MultiSignal[+T] {
type Element[+X] <: MultiSignalElement[X]
val element : Element[T]
def transform[R[+X] <: MultiSignal[X]](builder : MultiSignalBuilder[E, R] forSome { type E[+X] >: Element[X] }) : R[T] =
builder.buildNew(element)
}
abstract class MultiSignalBuilder[-E[+X] <: MultiSignalElement[X], +R[+X] <: MultiSignal[X]] {
def buildNew[T](element : E[T]) : R[T]
}
object myBuilder extends MultiSignalBuilder[MultiSignalElement, MultiSignal] {
def buildNew[T](e : MultiSignalElement[T]) = new MultiSignal[T]() {
type Element[+X] = MultiSignalElement[X]
val element = e
}
}
val multiSignal = new MultiSignal[Int] {
type Element[+X] = MultiSignalElement[X]
val element = new MultiSignalElement()
}
multiSignal.transform(myBuilder) //type error on this line
multiSignal.transform[MultiSignal](myBuilder) //type error on this line
。似乎必须要做的事实是E是一种更高级的类型。为什么这不起作用,有没有办法解决它?
{{1}}
答案 0 :(得分:4)
让我们一步一步地进行分析。
首先我们有
def transform[R](builder : MultiSignalBuilder[E, R] forSome { type E[+X] >: Element[X] }) : Unit = { }
这相当于声明:存在
type E[+X] >: Element[X]
我们可以定义
def transform[E[+X] >: Element[X], R[+_]](builder : MultiSignalBuilder[E, R] ) : Unit = { }
这里有错误
错误:(7,18)协变式X出现在逆变位置 输入类型[+ X]&gt;:类型为E的
这是件事。你期待你的神秘的存在协变类型应该是另一种协变类型的超类型。我认为这是第一件让编译器吓坏的事情。让我们改变与子类型的关系
def transform[E[+X] <: Element[X], R[+_]](builder : MultiSignalBuilder[E, R] ) : Unit = { }
现在我们有了
错误:(7,56)类型参数[E,R]不符合类 MultiSignalBuilder的类型参数绑定[-E [+ X]&lt;: MultiSignalElement [X],+ R [+ X]&lt ;: MultiSignal [X]]
因此,我们忘记要求MultiSignal[X]
参数R
的子类型。
让我们改变它
def transform[E[+X] <: Element[X], R[+X] <: MultiSignal[X]](builder : MultiSignalBuilder[E, R] ) : Unit = { }
现在
multiSignal.transform[MultiSignalElement,MultiSignal](myBuilder)
成功编译。
最后我们可以回到存在主义版本
def transform[R[+X] <: MultiSignal[X]](builder : MultiSignalBuilder[E, R] forSome {type E[+X] <: Element[X]}) : Unit = { }
用哪个
multiSignal.transform[MultiSignal](myBuilder)
成功编译。
可悲的是multiSignal.transform(myBuilder)
仍然没有编译。我认为编译器需要解决太多的类型关系。