据我所知,集合库中没有定义该map
方法的共享特征(很可能是因为 有不同的签名map
)。
我有一个具有更改事件的可观察值(想想 ui 系统中的属性)。可以使用map
方法映射可观察值。
然而,当我们使用已经有map
方法的类型时,我们应该能够使用map
.
所以而不是:
prop map { x =>
x map { actualX =>
//do something
}
}
我想像这样使用它:
prop map { actualX =>
//do something
}
我有一个简化的测试用例。首先是我使用的不同部分:
// leaving out the observable part
trait ObservableValue[T] {
def value: T
}
trait LowerPriorityImplicits {
// default implementation that adds a regular map method
implicit class RichObservableValue1[A](o: ObservableValue[A]) {
def map[B](f: A => B): ObservableValue[B] = new ObservableValue[B] {
def value = f(o.value)
}
}
}
object ObservableValue extends LowerPriorityImplicits {
// describe a type that has a map method
type HasMapMethod[A, Container[X]] = {
def map[B](f: A => B): Container[B]
}
// complex implementation that uses the builtin map if present
implicit class RichObservableValue2[A, Container[Z] <: HasMapMethod[Z, Container]](
o: ObservableValue[Container[A]]) {
def map[B](f: A => B): ObservableValue[Container[B]] =
new ObservableValue[Container[B]] {
def value = o.value.map(f)
}
}
}
如果上面的代码有什么(或者很多)错误,请告诉我。我想像这样使用它:
class TestCase extends ObservableValue[Option[Int]] {
def value = None
}
val x = new TestCase
x map { value =>
// this fails because the compiler finds the lower priority implicit
(value: Int).toString
}
// the method itself works fine
ObservableValue.RichObservableValue2(x) map { value =>
(value: Int).toString
}
如果我Container[B]
改成Any
它会发现RichObservableValue2
隐式转换。
我关于如何使用类型来选择隐式的知识是有限的。
我试图在以下位置找到答案,但主题有点压倒性:
- Scala 在哪里寻找隐式?
- 如何在 Scala 中链接隐式?
- Scala:隐式参数解析优先级
- http://eed3si9n.com/revisiting-implicits-without-import-tax
- ScalaReference.pdf 中的第 6.26.3 节“重载分辨率”
有没有办法解决这个挑战?
编辑
我知道FilterMonadic
收藏品的特点。我正在寻找一种能够识别类map
中定义的方法的解决方案Option
。
编辑 2
似乎该FilterMonadic
变体也不起作用。我添加RichObservableValue3
到RichObservableValue
对象。
implicit class RichObservableValue3[A, C[Z] <: FilterMonadic[Z, C[Z]]](o: ObservableValue[C[A]]) {
def map[B, That](f: A => B)(implicit bf: CanBuildFrom[C[A], B, That]): ObservableValue[That] = new ObservableValue[That] {
def value = o.value.map(f)
val change = o.change map (_ map f)
}
}
List[Int]
再一次,虽然 a是一个有效的参数,但没有选择隐式转换。我一定错过了选择隐式时使用的一些规则。