0
下面我有一個正在處理的庫的簡化版本。我在scala集合庫的CanBuildFrom特性之後對此進行了建模,因爲我的需求是相似的。但是,我無法完全推斷出所有情況下使用正確的生成器。在下面的示例中,如果我明確指定了要使用的構建器,但所有方法都能正常工作,但是當我沒有指定構建器時,雖然看起來orderedMultiSignalBuilder
應該是更嚴格的,但我得到了「模棱兩可的隱式值」的編譯錯誤具體比multiSignalBuilder
。我做錯了什麼?如何修改此庫設計,以便Scala能夠推斷出正確的構建器隱式參數?
trait Builder[-F, -SourceElement[X] <: Element[X]] {
type Result[X] <: MultiSignal[X]
type TargetElement[X] >: SourceElement[X]
def mapElement[T, U](element : SourceElement[T], value : U) : TargetElement[U] = {
throw new Exception() //not implemented yet
}
def buildNew[T, U](element : TargetElement[T]) : Result[U] = {
throw new Exception() //not implemented yet
}
}
object Builder {
implicit object multiSignalBuilder extends Builder[MultiSignal[Any], Element] {
type Result[X] = MultiSignal[X]
}
implicit def orderedMultiSignalBuilder[P] = new Builder[OrderedMultiSignal[Any] { type Position = P }, ({type λ[α] = OrderedElement[α, P]})#λ]() {
type Result[X] = OrderedMultiSignal[X] { type Position = P }
}
}
trait Element[+T] {
val value : T
}
trait OrderedElement[+T, +P] extends Element[T] {
}
trait MultiSignal[+T] {
type ElementType[+X] <: Element[X]
val element : ElementType[T]
def map[U](f : T => U) (implicit builder : Builder[this.type, ElementType]) : builder.Result[U] =
builder.buildNew(builder.mapElement(element, f(element.value)))
}
trait OrderedMultiSignal[+T] extends MultiSignal[T] {
type Position
type ElementType[+X] = OrderedElement[X, Position]
}
object multiSignal extends MultiSignal[Int] {
type ElementType[+X] = Element[X]
val element = new Element[Int] { val value = 0 }
}
object orderedMultiSignal extends OrderedMultiSignal[Int] {
type Position = Int
val element = new OrderedElement[Int, Int] { val value = 0 }
}
object Test {
multiSignal.map(_.toString)
orderedMultiSignal.map(_.toString) (Builder.multiSignalBuilder)
val result : OrderedMultiSignal[String] { type Position = Int } = orderedMultiSignal.map(_.toString) (Builder.orderedMultiSignalBuilder[Int])
//Next line gets compile error: ambiguous implicit values error
val result2 : OrderedMultiSignal[String] { type Position = Int } = orderedMultiSignal.map(_.toString)
}
您是否嘗試過將低優先級隱式放入'對象構建器'會擴展的特性? –