Scala 中的类型类模式不考虑继承?
在某些情况下,我正在使用类型类设计 API,但是我遇到了隐式解析的问题。如下所示,如果存在 A 类型的隐式对象,但将 B extends A
类型的对象传递给该方法,则无法找到隐式对象。有没有办法做到这一点,或者调用者是否必须将隐式对象放入每个子类的范围内?
这是一个示例:
class A
class B extends A
class T[+X]
object T {
implicit object TA extends T[A]
}
def call[X:T](x:X) = println(x)
// compiles
call(new A)
// doesn't compile
call(new B)
var a = new A
// compiles
call(a)
a = new B
// compiles
call(a)
val b = new B
// doesn't compile
call(b)
编译失败,输出如下:
/private/tmp/tc.scala:16: error: could not find implicit value for evidence parameter of type this.T[this.B] call(new B) ^ /private/tmp/tc.scala:28: error: could not find implicit value for evidence parameter of type this.T[this.B] call(b)
I am designing an API using type classes in some cases however I have encountered a problem with implicit resolution. As shown below, if there is an implicit object for type A but an object of type B extends A
is passed to the method, then an implicit object cannot be found. Is there a way to make this work or do callers have to put implicit objects into scope for each subclass?
Here is an example:
class A
class B extends A
class T[+X]
object T {
implicit object TA extends T[A]
}
def call[X:T](x:X) = println(x)
// compiles
call(new A)
// doesn't compile
call(new B)
var a = new A
// compiles
call(a)
a = new B
// compiles
call(a)
val b = new B
// doesn't compile
call(b)
This fails to compile with the following output:
/private/tmp/tc.scala:16: error: could not find implicit value for evidence parameter of type this.T[this.B] call(new B) ^ /private/tmp/tc.scala:28: error: could not find implicit value for evidence parameter of type this.T[this.B] call(b)
如果你对这篇内容有疑问,欢迎到本站社区发帖提问 参与讨论,获取更多帮助,或者扫码二维码加入 Web 技术交流群。
绑定邮箱获取回复消息
由于您还没有绑定你的真实邮箱,如果其他用户或者作者回复了您的评论,将不能在第一时间通知您!
发布评论
评论(3)
调用
call(new B)
意味着call[B](new B)(tB)
,使得tb是T[B]类型或其子类。 (需要 T 类型参数的方法只能需要 T 或 T 的子类,例如,不能使用Any
类型参数调用def foo(s: String)
) 。 T[A] 不是 T[B] 的子类型要修复此问题,您可以将 T 更改为定义
T[-X]
。这意味着编译器将认为 T[A] 是 T[B] 的子类型The call
call(new B)
meanscall[B](new B)(tB)
such that tb is of type T[B] or subclass of it. (A method that expects argument of type T can only expect T or subclass of T, e.g.,def foo(s: String)
cannot be called with argument of typeAny
). T[A] is not a subtype of T[B]To fix, you can change T to be defined
T[-X]
. This means that the compiler will consider T[A] to be a subtype of T[B]以下工作正常:
在您的情况下,编译失败,因为
def call[X:T](x:X) = println(x)
被视为call: [X](x: X)(隐式证据$1: T[X])单位
。为了传递子类型,您可以使用广义类型约束。The following works fine:
In your case compilation fails, because
def call[X:T](x:X) = println(x)
is treated ascall: [X](x: X)(implicit evidence$1: T[X])Unit
. In order to pass the subtype, you may use generalized type constraints.试试这个:
或者简单地:
Try this:
or simply: