1

我目前编写了一些实现类型类的类。我为此目的使用猫。在这种情况下,我有课程A[T]B[T] <: A[T]. A[T]是一个单子,所以在导入正确的库时,我可以写

val x: A[Int] = ???
x.flatMap(_)

但我不会写

val x: B[Int] = ???
b.flatMap(_)

因为 scala 没有找到 flatMap 运算符。相反,我必须写

val x: B[Int] = ???
(b: A[Int]).flatMap(_)

为此工作。这很尴尬,因为我希望子类继承超类的方法。

为了完整起见,我添加了一个没有依赖关系的最小示例来显示问题。其中,Filterable是一个类型类,由S.

object StackOverflowTest {
  class S[+T]

  class Q[+T] extends S[T]

  trait Filterable[F[+_]] {
    def filter[A](x: F[A]): F[A]
  }

  implicit class FilterOps[F[+_], A](y: F[A])(implicit ev: Filterable[F]) {
    def filter: F[A] = ev.filter(y)
  }

  implicit object SIsFilterable extends Filterable[S] {
    def filter[A](x: S[A]): S[A] = x
  }

  //def failing = {
  //  val q = new Q[Int]()
  //  val r = q.filter
  //}

  def working = {
    val q = new Q[Int]()
    val r = (q: S[Int]).filter
  }
}

failing定义无法编译,因为q.op未找到。另一方面,working通过首先转换为S. 我可以做些什么来使该failing示例适用于我的图书馆的用户?您必须强制转换为父类型才能使用它的方法,这感觉非常不自然。

请注意,我无法定义第二个实现的隐式对象,Filterable[Q]因为(new Q[Int]()).filter应该是 typeS[Int]而不是Q[Int]

4

1 回答 1

1

尝试替换SIsFilterable为:

implicit def sOrSubtypeIsFilterable [T[+_] <: S[_]] = new Filterable[T] {
  def filter[A](x: T[A]): T[A] = x
}
于 2016-05-19T19:41:08.850 回答