如何将类型类模式与子类型结合起来?

2024-02-02

假设我在 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 提供类型类实例的情况下完成这项工作?


对此有不同的可能解决方案,具体取决于我是否想解决问题仅适用于C,或者我是否想解决这个问题对于整个类型类.

仅适用于 C,而不是implicit object FooC ... we say:

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... with:

def foo[T](t: T)(implicit foo: Foo[_ >: T]) =
  foo.foo(t)

(感谢 #scala 居民 Daniel Sobral 和 Stefan Zeiger 的帮助。)

UPDATED2011 年 9 月 20 日包含我错过的“make Foo 逆变”解决方案

本文内容由网友自发贡献,版权归原作者所有,本站不承担相应法律责任。如您发现有涉嫌抄袭侵权的内容,请联系:hwhale#tublm.com(使用前将#替换为@)

如何将类型类模式与子类型结合起来? 的相关文章

随机推荐