EEC*_*LOR 5 types scala typeclass implicit-conversion structural-typing
据我所知,集合库中没有共享特征来定义map方法(很可能是因为有不同的签名map).
我有一个可观察的值(想想一个ui系统中的属性),它有一个change事件.可以使用map方法映射可观察值.
但是,当我们使用已经有map方法的类型时,我们应该能够使用内置方法map.
所以代替:
prop map { x =>
x map { actualX =>
//do something
}
}
Run Code Online (Sandbox Code Playgroud)
我想这样使用它:
prop map { actualX =>
//do something
}
Run Code Online (Sandbox Code Playgroud)
我有一个简化的测试用例.首先是我使用的不同部分:
// 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)
}
}
}
Run Code Online (Sandbox Code Playgroud)
如果上面的代码有问题(或许有很多),请告诉我.我想这样使用它:
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
}
Run Code Online (Sandbox Code Playgroud)
如果我改变Container[B]成Any会找到它的RichObservableValue2隐式转换.
关于如何使用类型来选择含义的我的知识是有限的.
我试图在以下位置找到答案,但主题有点压倒性:
无论如何要解决这个挑战吗?
我知道FilterMonadic收藏的特征.我正在寻找一种解决方案来识别类中map定义的方法Option.
似乎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)
}
}
Run Code Online (Sandbox Code Playgroud)
而且,即使a List[Int]是有效参数,也不会选择隐式转换.我必须遗漏一些在选择含义时使用的规则.
我终于找到了我丢失的部分。为了使隐式匹配,我必须添加以下类型参数:
T[Dummy <: Container[_]] <: ObservableValue[Dummy]
Run Code Online (Sandbox Code Playgroud)
结果对象:
object ObservableValue {
implicit class Mappable[A](o: ObservableValue[A]) {
def map[B](f: A => B): ObservableValue[B] = new ObservableValue[B] {
def value = f(o.value)
}
}
// FMC = FilterMonadicContainer
// D = Dummy
implicit class FilterMonadicMappable[A, FMC[D] <: FilterMonadic[D, FMC[D]]](o: ObservableValue[FMC[A]]) {
def map[B, That](f: A => B)(implicit bf: CanBuildFrom[FMC[A], B, That]): ObservableValue[That] = new ObservableValue[That] {
def value = o.value.map(f)
}
}
type HasMap[A, That[_]] = {
def map[B](f: A => B): That[B]
}
// OVC = ObservableValueContainer
// MC = MappableContainer
// D = Dummy
implicit class SimpleMappable[A, MC[D] <: HasMap[D, MC], OVC[D <: MC[_]] <: ObservableValue[D]](o: OVC[MC[A]]) {
def map[B](f: A => B): ObservableValue[MC[B]] = new ObservableValue[MC[B]] {
def value = o.value.map(f)
}
}
}
Run Code Online (Sandbox Code Playgroud)
| 归档时间: |
|
| 查看次数: |
615 次 |
| 最近记录: |