使类在Scala中扩展通用特征

时间:2018-06-17 11:55:39

标签: scala

我认为这应该可以替代类型类,但它不会:

trait Summable[T] {
  def sumWith(other: T): T
}

implicit class StringSummable(s: String) extends Summable[String]{
  def sumWith(other: String): String = s + other
}

def sumAll[T <: Summable[T]](list: List[T]): T = {
  list.reduceLeft((sum, element) => sum.sumWith(element))
}

sumAll(List("1","2","3"))

我有这个错误:inferred type arguments [lang.this.String] do not conform to method sumAll's type parameter bounds [T <: Summable[T]]

有没有办法使这项工作?

由于

1 个答案:

答案 0 :(得分:3)

是的,有一个“技巧”,它实际上是一个单一字符的变化:

':' -> '%'

从子类型到“隐式可兑换”界限:

trait Summable[T] {
  def sumWith(other: T): T
}

implicit class StringSummable(s: String) extends Summable[String]{
  def sumWith(other: String): String = s + other
}

def sumAll[T <% Summable[T]](list: List[T]): T = {
  list.reduceLeft((sum, element) => sum.sumWith(element))
}

sumAll(List("1","2","3"))

请注意,这往往会很快崩溃。例如,只要你需要一个返回空String的零值函数,你就会对这种方法感到不快,而对于一个类型类很简单(如Monoid[T]所示)。没有它,你甚至无法正确定义sumAll,因为它不适用于空列表。

请注意,到目前为止,历史发展已经远离隐式转换,而是转向类型类,而不是反过来。