Scala多态方法(或更高级的??)

时间:2015-04-11 20:42:55

标签: scala

我想定义一种压缩方法,将特定类型IntString的集合压缩为字符串。我想结合我目前拥有的两种方法:

  def compressString[T <: IndexedSeq[String]]: (T) => 
                        String = (array: T) => array.mkString(" ")
  def compressInt[T <: IndexedSeq[Int]]: (T) => 
                        String = (array: T) => array.mkString(" ")

进入一个方法。我尝试使用T[Int]做更高级的kinded类型,但它没有那样工作。我也尝试过:

   def compress[U, T <: IndexedSeq[U]]: (T) => String = 
                         (array: T) => array.mkString(" ")

然而,编译器给了我这个错误:

[error] type mismatch;
[error]  found   : Iterator[Int(in method compress)]
[error]  required: Iterator[scala.Int]
[error]     collect(array.iterator, Vector.empty[String], 0).mkString("\t")
[error]                   ^
[error] SVM.scala:55: type mismatch;
[error]  found   : java.lang.String
[error]  required: String(in method compress)
[error]   override def compress[String, T <: IndexedSeq[String]]: (T) => String = (array: T) => array.mkString("\t")

通常,我希望最终覆盖此方法并提供具体实现(处理Int的方法与String不同)。我如何结合这两种方法??

1 个答案:

答案 0 :(得分:8)

为了使你的泛型方法编译,你需要传递第一个类型的参数作为IndexedSeq的类型,即

def compress[U, T <: IndexedSeq[U]]: (T) => String = {
  (array: T) => array.mkString(" ")
}

then you can invoke it like,
val strings = compress[String,Vector[String]](Vector("a","b")) // strings: String = a b
val ints = compress[Int,Vector[Int]](Vector(1,2)) // ints: String = 1 2

但是,我认为type class在您希望具有ad hoc多态性的情况下更适合。

例如,您可以定义以下类型类:

@implicitNotFound("No compressor found for type ${T}")
trait Compressor[T] {
  def compress(array: IndexedSeq[T]): String
}

并为要支持压缩的每种类型创建一个实现

implicit val stringCompressor = new Compressor[String] {
  override def compress(array: IndexedSeq[String]): String = array.mkString(" ")
}

implicit val intCompressor = new Compressor[Int] {
  override def compress(array: IndexedSeq[Int]): String = array.mkString(" ")
}

然后你可以直接调用方法

val strings = stringCompressor.compress(Vector("a","b"))  // strings: String = a b
val ints = intCompressor.compress(Vector(1,2)) // ints: String = 1 2

或者您可以定义采用隐式参数

的通用方法
def compress[T](array: IndexedSeq[T])(implicit compressor: Compressor[T]): String = {
  compressor.compress(array)
}

// or equivalently
def compress[T: Compressor](array: IndexedSeq[T]): String = {
  implicitly[Compressor[T]].compress(array)
}

并像这样使用

val strings = compress(Vector("a","b"))  // strings: String = a b
val ints = compress(Vector(1,2))         // ints: String = 1 2

如果范围中没有定义隐式压缩器,编译器会给出错误,例如

compress(Vector(true, false))
error: No compressor found for type Boolean
          compress(Vector(true, false))
                  ^

希望它有所帮助。