类型和子类型

时间:2012-03-20 10:58:55

标签: scala typeclass implicit subtyping

我有以下代码定义类型类。

trait Foo[T] {
  def toFoo(x: T): String
}

trait Foos {
  def toFoo[T](f: T => String): Foo[T] = new Foo[T] {
    def toFoo(x: T): String = f(x)
  }
}

object Foo extends Foos {
  def toFoo[A: Foo](a: A) = implicitly[Foo[A]].toFoo(a)
  implicit def AToFoo: Foo[A] = toFoo { c =>
    "A"
   }
  implicit def BToFoo[T]: Foo[B] = toFoo { c  => 
    "B"
  }

  implicit def ListToFoo[T: Foo]: Foo[List[T]] = toFoo { c =>
    c.map(toFoo(_)).
  }
}

class A
class B extends A

如果我有toFoo(List(new A, new B),我现在得到List("A", "A")而不是List("A", "B")。对于类型为BtoFoo的类,如何确保使用AToFoo方法而不是B

1 个答案:

答案 0 :(得分:2)

隐式解析是一种纯粹的编译时机制。这里区分子类型的简单方法是在隐含内部匹配。完全删除BToFoo,而是将A版本处理两种情况

implicit val AIsFoo : Foo[A] = toFoo { 
  case b: B => "B"
  case a: A => "A"
}

当然,也可以委托部分层次结构的方法。您可以委托A中的方法,在B中进行覆盖,并且仍然可以使用类型类对List进行操作,您无法在其中添加方法。

您也可以考虑声明Foo逆变。