我目前编写了一些实现类型类的类。我为此目的使用猫。在这种情况下,我有课程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]
。