Scala多态方法(或更高种类??)

Scala多态方法(或更高种类??),scala,Scala,我想定义一个压缩方法,将特定类型Int或String的集合压缩为字符串。我想结合我目前拥有的两种方法: def compressString[T <: IndexedSeq[String]]: (T) => String = (array: T) => array.mkString(" ") def compressInt[T <: IndexedSeq[Int]]: (T) =>

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

  def compressString[T <: IndexedSeq[String]]: (T) => 
                        String = (array: T) => array.mkString(" ")
  def compressInt[T <: IndexedSeq[Int]]: (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。如何组合这两种方法???

为了使泛型方法能够编译,您需要将第一个类型参数作为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
并为您想要支持压缩的每种类型创建一个实现

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))
                  ^

希望有帮助。

为了使泛型方法能够编译,您需要将第一个类型参数作为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
并为您想要支持压缩的每种类型创建一个实现

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))
                  ^

希望有帮助。

Intin方法compress通常意味着您已经用Int名称实例化了一个新的泛型。您只需要一个compress版本,它可以在seq中的任何IndexedSeq[\u]无规则类型上运行,对吗?@isomarte yes,但我也希望标记类型,因为我希望能够为内部的不同类提供不同的方法。比如,如果基础类型是String,我会做一些事情,如果基础类型是Int,我会做其他事情。Intin方法compress通常意味着您已经实例化了一个名为Int的新泛型。您只需要一个版本的compress,它可以在seq中的任何IndexedSeq[u]类型上运行,对吗?@isomarte yes,但我也希望标记类型,因为我希望能够为内部的不同类提供不同的方法。比如,如果基础类型是String,我会做一些事情,如果基础类型是Int,我会做其他事情。我甚至不知道我可以在trait上使用关键字new@AllenNie是的,它只是创建了一个新的匿名实例。您可以在Java中对通常用于假装具有第一类函数的函数接口的接口执行相同的操作。您的第二个示例正是我想要做的:重写原始方法,并为每种类型Int和String提供一个新的特殊方法…但是有没有更简单的方法,我可以直接调用compress而不是compressInt或compressString?回答得好。您可以添加一个关于Scala中未初始化的类型类的典型用法的注释,即def needsCompressor[T:Compressor]……我所知道的最好的资源就在这里。你会注意到Twitter将我称之为类型类的东西称为其他类型边界,根据我的经验,这些术语现在在scala中有些混乱。其他文档颠倒了符号。如果您愿意,可以再问一个关于scala中类型类的问题,我找不到一个已经被问过的问题。。。我很乐意回答这个问题。只需在此处发布新问题的链接或聊天。我不应该在这里回答,因为这是违反SO政策的。问到这个问题,我甚至不知道我可以在特质上使用关键词new@AllenNie是的,它只是创建了一个新的匿名实例。您可以在Java中对通常用于假装具有第一类函数的函数接口的接口执行相同的操作。您的第二个示例正是我想要做的:重写原始方法,并为每种类型Int和String提供一个新的特殊方法…但是有没有更简单的方法,我可以直接调用compress而不是compressInt或compressString?回答得好。您可以添加一个关于Scala中未初始化的类型类的典型用法的注释,即def needsCompressor[T:Compressor]……我所知道的最好的资源就在这里。你会注意到Twitter将我称之为类型类的东西称为其他类型边界,根据我的经验,这些术语现在在scala中有些混乱。其他文档颠倒了符号。如果您愿意,可以再问一个关于scala中类型类的问题,我找不到一个已经被问过的问题。。。我很乐意回答这个问题。只需在此处发布新问题的链接或聊天。我不应该在这里回答,因为这是违反SO政策的。关于问题的离题