在列表

时间:2015-12-16 15:15:21

标签: scala types

我试图声明一个带有两个类型参数的case类:具体类型A和类型构造函数D,被约束为已知类型的子类。我的案例类将包含List[D[A]]

我遇到的问题是,每当我在该列表上进行映射时,我似乎都会丢失D所包含类型的信息。

以下是我所拥有的:

// Represents a named collection of documents of type A
trait Documents[A] {
  def name: String
  def take(target: Int): Documents[A]

  // [...]
}

// Represents a collection of named collections of documents.
// A is the type of a document, D that of a named collection of documents
case class Data[A, D[_] <: Documents[_]](docs: List[D[A]]) {
  // Makes sure no D contains more than target documents
  def cap(target: Int): Data[A, Documents] = {
    Data(docs.map(_.take(target)))
  }

  // [...]
}

无法使用以下令人困惑的错误消息进行编译:

type mismatch;
[error]  found   : List[Documents[_]]
[error]  required: List[Documents[A]]
[error]     Data(docs.map(_.take(target)))
[error]                  ^

我不明白将函数D[A] => Documents[A]应用于D[A]如何产生Documents[_] ......

1 个答案:

答案 0 :(得分:1)

问题是Documents[_]正在使用存在类型,这意味着您告诉编译器您不关心D中包含的类型。因此,即使您指定docsList[D[A]],编译器也只会将其视为List[D[_]]。你真正想要的是使用自由类型参数,而不是类型约束中的通配符。即D[B] <: Documents[B]

import scala.language.higherKinds

trait Documents[A] {
  def name: String
  def take(target: Int): Documents[A]
}

case class Data[A, D[B] <: Documents[B]](docs: List[D[A]]) {

  def cap(target: Int): Data[A, Documents] = {
    Data(docs.map(_.take(target)))
  }

}