Я бы пошел с классом типа :
trait Semigroup[A] {
def mappend(a0: A, a: A): A
}
object Semigroup {
implicit val intAdditionSemigroup: Semigroup[Int] = new Semigroup[Int] {
override def mappend(a0: Int, a: Int): Int = a0 + a
}
}
Когда вы хотите использовать его, вы добавляете его как неявное ограничение на параметр типа:
def foo[A](a0: A, a: A)(implicit semigroup: Semigroup[A]): A = {
semigroup.mappend(a0, a)
}