如何在Scala中为泛型类型提供默认类型类?

时间:2015-06-06 07:32:33

标签: scala generics types typeclass type-parameter

在Scala中,如果你创建一个类型类,比如代数结构Monoid[T],你可以为不同类型的monoid提供许多默认的类型类实现。

假设将monoid定义为:

trait Monoid[T] {
  def op(x: T, y: T): T
  def id: T
}

由于连接操作下的String形成一个monoid,我们可以为String提供一个默认的monoid:

implicit object StringMonoid extends Monoid[String] {
  override def op(a: String, b: String): String = a + b
  override def id: String = ""
}

这很简单,因为String不是通用类型。

我要求的是如何为Seq[T] s 提供默认的monoid,其中type参数阻止我像上面那样创建隐式对象。

我能做到:

class SeqMonoid[T] extends Monoid[Seq[T]] {
  override def op(a: Seq[T], b: Seq[T]): Seq[T] = a ++ b
  override def id: Seq[T] = Nil
}
implicit object intSeqMonoid extends SeqMonoid[Int]
implicit object doubleSeqMonoid extends SeqMonoid[Double]
implicit object stringSeqMonoid extends SeqMonoid[String]
...

但这种方法并没有利用泛型类型的美感。

所以,一般来说,我的问题是:在Scala中有什么办法可以为泛型类型提供类型类实现吗?

2 个答案:

答案 0 :(得分:7)

您可以提供具有所需类型的隐式函数:

implicit def SeqMonoid[T]: Monoid[Seq[T]] = new Monoid[Seq[T]] {
  override def op(a: Seq[T], b: Seq[T]): Seq[T] = a ++ b
  override def id: Seq[T] = Nil
}

答案 1 :(得分:0)

变化而不重复Seq[T]

object Monoid {
  implicit def seqMonoid[T]:Monoid[Seq[T]] = {
    type S = Seq[T]
    new Monoid[S] {
     def op(x: S, y: S) = x ++ y
     def id = Nil
    }
  }
}