Как предоставить класс типов по умолчанию для универсальных типов в Scala?

В Scala, если вы создаете класс типов, скажем, алгебраическую структуру Monoid[T], вы можете предоставить множество реализаций классов типов по умолчанию для различных типов, являющихся моноидами.

Предположим, что моноид определяется как:

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

Поскольку Strings в операции конкатенации образуют моноид, мы можем предоставить моноид по умолчанию для Strings следующим образом:

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

Это довольно просто, так как String не является универсальным типом.

Я прошу как предоставить моноид по умолчанию для Seq[T]s, в котором параметр типа не позволяет мне создавать неявный объект, как я сделал выше.

Я мог бы сделать:

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 предоставить реализации классов типов для универсальных типов?


person Yuhuan Jiang    schedule 06.06.2015    source источник


Ответы (2)


Вы можете предоставить неявную функцию с требуемым типом:

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
}
person Kolmar    schedule 06.06.2015
comment
Разве это не будет создавать новый объект каждый раз, когда потребуется Monoid[Seq[T]]? - person Yuhuan Jiang; 06.06.2015
comment
@YuhuanJiang Да, но у вас действительно нет выбора, если вы хотите, чтобы он был универсальным. - person Michael Zajac; 06.06.2015

Вариант без повторения 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
    }
  }
}
person Victor Moroz    schedule 06.06.2015