Scala:当隐式证据参数具有表示类型时,返回复制方法的类型

时间:2012-07-20 23:06:07

标签: scala type-parameter

假设我有一个带有类型参数的类和一个只有在使用具有表示类型的特定特征对类进行参数化时才应返回实例副本的方法。我可以很容易地做到这一点。我不能做的是提出一种合理的返回方式:

case class Foo[+A](a: A) {
  // Compiles
  def gotFooBar(implicit evidence: A <:< Bar[_]) = copy(a = a.Copy())

  // Does not compile
  def gotFooBar(implicit evidence: A <:< Bar[_]): Foo[A] = copy(a = a.Copy())
}

trait Bar[+B <: Bar[B]] {
  def Copy(): B // Return underlying type
}

case class Grill() extends Bar[Grill] {
  def Copy() = Grill()
}

该函数的返回类型是什么,或者更重要的是,我如何设置类型以便返回类型?有人还可以指出真正的返回类型如何成为Foo[A]的超类型吗?

2 个答案:

答案 0 :(得分:2)

好吧,因为您只需要Bar[_],因此调用Any会得到a.Copy。您需要gotFooBar方法的类型参数:

case class Foo[+A](a: A) {
   def gotFooBar[B <: Bar[B]](implicit evidence: A <:< B): Foo[B] = {
      val bar = a: B
      copy(a = bar.Copy())
   }
}

第二个问题是,如何强制Foo[B]Foo[A]的超类型。您只需添加A作为B的下限:

def gotFooBar[B >: A <: Bar[B]](implicit evidence: A <:< B): Foo[B]

答案 1 :(得分:0)

这是@ 0__答案的后续答案。如果A有与之关联的清单,情况就会变得复杂一些:

case class Foo[+A : Manifest](a: A)

方法类型参数B也需要一个Manifest(即使你不使用它)。添加清单(: Manifest)的常用方法也不起作用,因为当方法也有隐式参数(在这种情况下为implicit evidence)时,不允许这样做。可以将Manifest放在隐式参数列表中,如下所示:

def gotFooBar[B >: A <: Bar[B]]
  (implicit m: Manifest[B], evidence: A <:< B): Foo[B] =
  copy(a = a.Copy())