缺少抽象类型成员Array的类清单

时间:2011-11-13 01:05:03

标签: scala manifest abstract-type

我正在寻找在数组实例化中提供类清单的建议。我重构了这段代码(编译得很好):

trait Ref[A]
trait Struct[A] {
  val arr = new Array[Ref[A]](1)
}

到此:

trait Ref[S <: Sys[S], A]
trait Sys[Self <: Sys[Self]] {
  type R[A] <: Ref[Self, A]
}

trait Struct[S <: Sys[S], A] {
  val arr = new Array[S#R[A]](1)
}

此操作失败,并显示消息"cannot find class manifest for element type S#R[A]"

那我该怎么解决呢?

2 个答案:

答案 0 :(得分:2)

我可以提出一个涉及简单间接的解决方案:

trait Sys[Self <: Sys[Self]] {
  type R[A] <: Ref[Self, A]
  def newRefArray[A](size: Int): Array[Self#R[A]]
}

trait Struct[S <: Sys[S], A] {
  def sys: S
  val arr = sys.newRefArray[A](1)
}

答案 1 :(得分:2)

您的问题是Array在其类型参数中不变,需要一个精确的类型参数。您在type R中对Sys的定义仅提供上限。

您可以通过使用相等替换R的上限来解决定义网站上的问题,

trait Ref[S <: Sys[S], A]
trait Sys[Self <: Sys[Self]] {
  type R[A] = Ref[Self, A]        // '=' not '<:'
}

trait Struct[S <: Sys[S], A] {
  val arr = new Array[S#R[A]](1)  // OK
}

或者,如果您希望在R[A]中打开Sys,则可以通过细化在用户站点指定等式约束,如此,

trait Ref[S <: Sys[S], A]
trait Sys[Self <: Sys[Self]] {
  type R[A] <: Ref[Self, A]       // Back to an upper bound
}

trait Struct[S <: Sys[S] { type R[A] = Ref[S, A] }, A] {
//                       ^^^^^^^^^^^^^^^^^^^^^^^^^
//                       Assert the equality via a refinement
  val arr = new Array[S#R[A]](1)  // OK
}

如果您无法通过这两种方式确定type R,那么您别无选择,只能自己明确提供ClassManifest,

trait Ref[S <: Sys[S], A]
trait Sys[Self <: Sys[Self]] {
  type R[A] <: Ref[Self, A]
}

trait Struct[S <: Sys[S], A] {
  implicit val rM : ClassManifest[S#R[A]] // Provided manifest later ...
  val arr = new Array[S#R[A]](1)  // OK 
}

class SomeSys extends Sys[SomeSys] {
  type R[A] = Ref[SomeSys, A]
}

val s = new Struct[SomeSys, Int] {
  val rM = implicitly[ClassManifest[SomeSys#R[Int]]]
  //                                ^^^^^^^^^^^^^^
  //                                Precise type known here
}

选择哪一项很大程度上取决于你的大背景。