5

据我所知,集合库中没有定义该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隐式转换。

我关于如何使用类型来选择隐式的知识是有限的。

我试图在以下位置找到答案,但主题有点压倒性:

有没有办法解决这个挑战?

编辑

我知道FilterMonadic收藏品的特点。我正在寻找一种能够识别类map中定义的方法的解决方案Option

编辑 2

似乎该FilterMonadic变体也不起作用。我添加RichObservableValue3RichObservableValue对象。

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是一个有效的参数,但没有选择隐式转换。我一定错过了选择隐式时使用的一些规则。

4

1 回答 1

0

我终于找到了我缺少的部分。为了使隐式匹配,我必须添加以下类型参数:

T[Dummy <: Container[_]] <: ObservableValue[Dummy]

结果对象:

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)
    }
  }

}
于 2013-02-14T23:39:22.073 回答