代码之家  ›  专栏  ›  技术社区  ›  Loic

使类在scala中扩展通用特性

  •  0
  • Loic  · 技术社区  · 6 年前

    我认为这应该可以使类型类成为一种简单的替代方法,但它不能:

    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 回复  |  直到 6 年前
        1
  •  3
  •   Andrey Tyukin    6 年前

    是的,有一个“把戏”,它实际上是一个单一的角色变化:

    ':' -> '%'
    

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

    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 对于这种方法,您基本上不太走运,而对于typeclass(如 Monoid[T] 显示)。没有它,你甚至无法定义 sumAll 正确地说,因为它不适用于空列表。

    注意到迄今为止的历史发展 远离隐式转换 对类型类,而不是反过来。