如何通过Int和Double的“超类”定义直方图特征?

时间:2012-10-04 16:33:15

标签: scala generics numeric boilerplate

IntHistogram统计单词并显示计数降序:

object IntHistogram {

  def main(args: Array[String]) {
    val wordsToCount = "foo foo bar foo bar wtf foo bar".split(" ")
    val histogram = new IntHistogram
    for (word <- wordsToCount) histogram(word) += 1
    println(histogram)
    /* 
       (foo,4)
       (bar,3)
       (wtf,1)
    */
  }

}

class IntHistogram extends collection.mutable.HashMap[String,Int] {
  override def default(key:String) = 0
  def descendingPairs = toList.sortBy(_._2).reverse
  override def toString() = descendingPairs.mkString("\n")
}

我需要DoubleHistogram,我使用复制粘贴,因为我无法弄清楚如何定义通用的“Histogram [NumberSuperClassOfIntAndDouble]”特性:

class DoubleHistogram extends collection.mutable.HashMap[String,Double] {
  override def default(key:String) = 0
  def descendingPairs = toList.sortBy(_._2).reverse
  override def toString() = descendingPairs.mkString("\n")
}

一个聪明/知识渊博的人能告诉我如何定义这样一个超级版本,所以我可以避免丑陋的复制粘贴样板吗?

提前致谢,

PT

P.S。我真的希望直方图成为一个特征,所以我可以将直方图行为混合到任何数值映射中。实际上除了降序toString方法之外,我还需要很多行为;我简化了这个问题。 Num是Int和Double的虚构数字超类:

trait Histogram[Num] extends collection.Map[String,Num] {
  override def default(key:String) = 0
  def descendingPairs = toList.sortBy(_._2).reverse
  override def toString() = descendingPairs.mkString("\n")
}

我尝试使用数字,数字,导入Ordering.Implicits._,各种各样的东西......无济于事。

1 个答案:

答案 0 :(得分:2)

这似乎与Numeric一样正常。并非由于Histogram上的上下文限制,您无法使N成为特征,但IntHistogramDoubleHistogram可能是特征。

object IntHistogram {

  def main(args: Array[String]) {
    val wordsToCount = "foo foo bar foo bar wtf foo bar".split(" ")
    val histogram = new IntHistogram {}
    for (word <- wordsToCount) histogram(word) += 1
    println(histogram)
    /* 
       (foo,4)
       (bar,3)
       (wtf,1)
    */
  }

}

abstract class Histogram[N:Numeric] extends collection.mutable.HashMap[String,N] {
  override def default(key:String) = implicitly[Numeric[N]].zero
  def descendingPairs = toList.sortBy(_._2).reverse
  override def toString = descendingPairs.mkString("\n")
}

trait IntHistogram extends Histogram[Int]
trait DoubleHistogram extends Histogram[Double]

如果你真的需要直方图作为特质,你可以这样做:

trait Histogram[N] extends collection.mutable.HashMap[String,N] {
  implicit val n:Numeric[N]
  override def default(key:String) = n.zero
  def descendingPairs = toList.sortBy(_._2).reverse
  override def toString = descendingPairs.mkString("\n")
}

但是你必须在main中实例化它:

val histogram = new Histogram[Int] { val n = implicitly[Numeric[Int]] }