下面我有一个我正在处理的库的简化版本。我在scala集合库的CanBuildFrom特性之后对此进行了建模,因为我的要求类似。但是,我无法推断出在所有情况下都要使用的正确构建器。在下面的示例中,如果我明确指定要使用的构建器,则所有方法都有效,但是对于"模糊的隐式值"我得到了编译错误。当我没有指定构建器时,即使orderedMultiSignalBuilder
似乎应该严格比multiSignalBuilder
更具体。我做错了什么?
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)
}
答案 0 :(得分:2)
trait Builder[-F, -Source[X] <: Element[X]] {
type Result[X] <: MultiSignal[X]
}
trait Element[+T] {
val value: T
}
trait OrderedElement[+T, +P] extends Element[T]
object MultiSignal {
implicit object builder extends Builder[MultiSignal[Any], Element] {
type Result[X] = MultiSignal[X]
}
}
trait MultiSignal[+T] {
type Elem[X] <: Element[X]
def map[U](f: T => U)(implicit b: Builder[this.type, Elem]): b.Result[U] = ???
}
object OrderedMultiSignal {
implicit def builder[P] =
new Builder[OrderedMultiSignal[Any] { type Pos = P },
({type λ[α] = OrderedElement[α, P]})#λ]() {
type Result[X] = OrderedMultiSignal[X] { type Pos = P }
}
}
trait OrderedMultiSignal[+T] extends MultiSignal[T] {
type Pos
type Elem[X] = OrderedElement[X, Pos]
}
object multi extends MultiSignal[Int] {
type Elem[X] = Element[X]
}
object ordered extends OrderedMultiSignal[Int] {
type Pos = Int
}
object Test {
multi .map(_.toString)
ordered.map(_.toString)
val res0: MultiSignal [String] = multi .map(_.toString)
val res1: OrderedMultiSignal[String] {type Pos=Int} = ordered.map(_.toString)
}
中的两个隐式构建器与Scala的推断观点的特殊性不相同 。如果您查看集合中如何定义构建器,您会注意到它们是特定集合类型的伴随对象的一部分。如果将构建器移动到相应的随播类型,则优先级将起作用:
this.type
在map
中使用Repr
对我来说也是错误的。它可以在这里工作,但我认为你应该用Unmet dependency: xscrnsaver
QtWebEngine will not be built.
替换它,它是信号的另一个类型成员。