根据参数类型列出

时间:2012-12-16 12:32:57

标签: scala

以下我有:

trait Elem {
  def compare: Int
}

case class DiffElem(weight: Int, len: Int) extends Elem {
  def compare = weight - len;
}

现在基于compare函数可以有许多Elem的子类。 现在我有一个函数,它从文件读取输入并生成DiffElem的列表:

def getInput[T <: Elem](): List[T] = {
  var ans: List[T] = List.empty[T]
  for (line <- Source.fromFile("src/week1/jobs.txt").getLines()) {
    val diff = line.split(" ")
    ans = ans match{
      case i:List[DiffElem] =>  new DiffElem(Integer.parseInt(diff(0)), Integer.parseInt(diff(1))) :: ans;
      case _ => ???
    }

  }
  ans
}

但编译器不允许该操作,显然::遵循反向方差类型,我试图做不变性。如果我将函数签名转换为T >: Elem,那么它可以工作,但目的没有解决。

有更好的方法吗?

2 个答案:

答案 0 :(得分:3)

如果你在getInput中构建DiffElem,那么你想获得任意T&lt;:Elem列表的方式(以及为什么)?要做这样的事情,你应该能够从DiffElem转换为任何另一个T&lt;:Elem,并且可以使用隐式捕获可转换性:

  def getInput[T <: Elem](implicit conv: DiffElem => T): List[T] = ...

,但你真的想要吗?如果您对DiffElem的列表感到满意,可以用这种方式重写功能:

  def getInput(): List[DiffElem] =
    Source.fromFile("src/week1/jobs.txt").getLines().map { line =>
      val diff = line.split(" ")
      DiffElem(
        Integer.parseInt(diff(0)),
        Integer.parseInt(diff(1))
      )
    } toList

map是高阶函数,它捕获序列中每个元素的变换,并将其funarg应用于此元素。

<强>更新: 为了制作模块化类型驱动列表,我建议使用:

  def getInput[E <: Elem](implicit mkE: (Int, Int) => E): List[E] = {
    Source.fromFile("src/week1/jobs.txt").getLines().map { line =>
      val diff = line.split(" ")      
      mkE(diff(0).toInt, diff(1).toInt)      
    } toList
  }

现在,对于您想要获得的任何E&lt;:Elem,列表,您应该提供类型(Int,Int)=&gt;的隐式值。 E进入范围,如:

  implicit val diffElemBuilder = {
    (a, b) => DiffElem(a, b)
  }

在任何可见的隐式范围内,您都可以使用这样的getInput:

val xs = getInput[DiffElem]

答案 1 :(得分:-1)

您可以重新构建代码并使用排名较高的多态函数而不是模式匹配。