Type Class syntax in Scala

Coding against the typeclass:

trait Monoid[T] {
  def zero: T
  def add(a: T, b: T): T
}

object TypeClass {

  object IntSum extends Monoid[Int] {
    def zero = 0
    def add(a: Int, b: Int): Int = a + b
  }

  object StringSum extends Monoid[String] {
    def zero = ""
    def add(a: String, b: String): String = a + b
  }

  def sum[T](xs: List[T], monoid: Monoid[T]): T = {
    xs.foldLeft(monoid.zero)(monoid.add)
  }

}

object Test {
  import TypeClass._

  val sumInt: Int = sum(List(1,2,3), IntSum)
  val sumStr: String = sum(List("oh", "hey"), StringSum)
}

Using implicit parameters makes it a lot neater:

trait Monoid[T] {
  def zero: T
  def add(a: T, b: T): T
}

object TypeClass {

  implicit object IntSum extends Monoid[Int] {
    def zero = 0
    def add(a: Int, b: Int): Int = a + b
  }

  implicit object StringSum extends Monoid[String] {
    def zero = ""
    def add(a: String, b: String): String = a ++ b
  }

  def sum[T](xs: List[T])(implicit monoid: Monoid[T]): T = {
    xs.foldLeft(monoid.zero)(monoid.add)
  }

}

object Test {
  import TypeClass._

  val sumInt: Int = sum(List(1,2,3))
  val sumStr: String = sum(List("oh", "hey"))
}

I can also use an implicit class if I want sum to be a method; this way the compiler will see if it can convert any List[T] into a SummableThingy that has the new summarise method defined.

trait Monoid[T] {
  def zero: T
  def add(a: T, b: T): T
}

object TypeClass {

  implicit object IntSum extends Monoid[Int] {
    def zero = 0
    def add(a: Int, b: Int): Int = a + b
  }

  implicit object StringSum extends Monoid[String] {
    def zero = ""
    def add(a: String, b: String): String = a ++ b
  }

  def sum[T](xs: List[T])(implicit monoid: Monoid[T]): T = {
    xs.foldLeft(monoid.zero)(monoid.add)
  }

  implicit class SummableThingy[T](x: List[T]) {
    def summarize(implicit monoid: Monoid[T]): T = sum(x)
  }
}

object Test {
  import TypeClass._

  List(1, 2, 3).summarize
  List("oh, hey").summarize
}