如何将类型类模式与子类型结合起来?
假设我在 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)
^
Doh!如何在不必显式为 D 提供类型类实例的情况下完成这项工作?
Suppose I'm using the typeclass pattern in Scala. Here's how I make a class C
part of the typeclass 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!
So far so good. But suppose I have a subclass D of C, and I want instances of D to be "in" the typeclass too:
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)
^
Doh! How do I make this work without having to explicitly provide a typeclass instance for D?
如果你对这篇内容有疑问,欢迎到本站社区发帖提问 参与讨论,获取更多帮助,或者扫码二维码加入 Web 技术交流群。
绑定邮箱获取回复消息
由于您还没有绑定你的真实邮箱,如果其他用户或者作者回复了您的评论,将不能在第一时间通知您!
发布评论
评论(1)
对此有不同的可能解决方案,具体取决于我是否想要仅针对 C 解决问题,或者是否想要针对整个类型类解决问题。
仅对于 C,而不是
隐式对象 FooC ...
我们说:要修复所有 Foo,使其逆变:
或者如果由于某种原因您不能或不想这样做,您可以将
def foo...
替换为:(感谢 #scala denizens Daniel Sobral 和 Stefan Zeiger 的帮助。)
更新 2011 年 9 月 20 日包含“make” Foo 逆变”解决方案,我错过了
There are different possible solutions for this, depending on whether I want to fix the problem only for C, or whether I want to fix the problem for the entire typeclass.
For C only, instead of
implicit object FooC ...
we say:To fix all of Foo, make it contravariant:
Or if for some reason you can't or don't want to do that, you can replace
def foo...
with:(Thanks to #scala denizens Daniel Sobral and Stefan Zeiger for their help.)
UPDATED Sep 20 2011 to include the "make Foo contravariant" solution, which I missed