假设我在Scala中使用了类型类模式。这是我如何制作C级课程 类型类Foo的一部分:
Welcome to Scala version 2.9.0.1 (Java HotSpot(TM) 64-Bit Server VM, Java 1.6.0_26).
scala> trait Foo[T] { def foo(t: T) }
defined trait Foo
scala> def foo[T : Foo](t: T) { implicitly[Foo[T]].foo(t) }
foo: [T](t: T)(implicit evidence$1: Foo[T])Unit
scala> class C
defined class C
scala> foo(new C)
<console>:11: error: could not find implicit value for evidence parameter of type Foo[C]
foo(new C)
^
scala> implicit object FooC extends Foo[C] { override def foo(c: C) { println("it's a C!") } }
defined module FooC
scala> foo(new C)
it's a C!
到目前为止一切顺利。但是假设我有一个C的子类D,我希望D的实例也在“类型”中:
scala> class D extends C
defined class D
scala> foo(new D)
<console>:13: error: could not find implicit value for evidence parameter of type Foo[D]
foo(new D)
^
卫生署!如何在不必为D?
显式提供类型类实例的情况下完成此工作答案 0 :(得分:15)
对此有不同的可能解决方案,具体取决于我是否只想修复问题仅针对C ,或者我是否要解决整个类型类的问题
仅限C,而不是implicit object FooC ...
我们说:
implicit def CIsFoo[T <: C]: Foo[T] =
new Foo[T] { override def foo(t: T) { println("it's a C!") } }
要修复所有Foo,请将其变为逆变:
trait Foo[-T] { def foo(t: T) }
或者,如果由于某种原因您不能或不想这样做,您可以将def foo...
替换为:
def foo[T](t: T)(implicit foo: Foo[_ >: T]) =
foo.foo(t)
(感谢#scala居民Daniel Sobral和Stefan Zeiger的帮助。)
更新 2011年9月20日加入“make Foo contravariant”解决方案,我错过了