Reputation: 1154
I was trying to implement SemiGroup in a generic manner for most of the scala types including collections. But when it comes to collection, I was stuck to implement the implicit SemiGroupImplicitTypes for collections.
For example: If I want to implement a SemiGroup[List[T]], It expects another param for the type of elements in List, I don't want to implement SemiGroup[List[Int]], SemiGroup[List[Double]] separately, want a single implementation for implicit, which will implement it for all types of List.
trait Semigroup[T] extends Any {
def combine(a: T, b: T): T
}
object SemiGroup {
def apply[T](a: T, b: T)(implicit ev: Semigroup[T]): T = ev.combine(a,b)
}
class SemiGroupList[T] extends Semigroup[List[T]] {
override def combine(a: List[T], b: List[T]): List[T] = a ++ b
}
class SemiGroupSeq[T] extends Semigroup[Seq[T]] {
override def combine(a: Seq[T], b: Seq[T]): Seq[T] = a ++ b
}
class SemiGroupMap[U, V] extends Semigroup[Map[U,V]] {
override def combine(a: Map[U, V], b: Map[U, V]): Map[U, V] = a ++ b
}
class SemiGroupNumber[@specialized (Int, Double, Float, Long) T](implicit numeric: Numeric[T]) extends Semigroup[T] {
override def combine(a: T, b: T): T = numeric.plus(a, b)
}
object SemiGroupImplicitTypes {
implicit object IntSemiGroup extends SemiGroupNumber[Int]
implicit object LongSemiGroup extends SemiGroupNumber[Long]
implicit object DoubleSemiGroup extends SemiGroupNumber[Double]
implicit object FloatSemiGroup extends SemiGroupNumber[Float]
}
import SemiGroupImplicitTypes._
SemiGroup[Long](1,2)
Upvotes: 0
Views: 122
Reputation: 1154
trait Semigroup[T] extends Any {
def combine(a: T, b: T): T
}
object SemiGroup {
def apply[T](a: T, b: T)(implicit ev: Semigroup[T]): T = ev.combine(a,b)
}
class SemiGroupList[T] extends Semigroup[List[T]] {
override def combine(a: List[T], b: List[T]): List[T] = a ++ b
}
class SemiGroupSeq[T] extends Semigroup[Seq[T]] {
override def combine(a: Seq[T], b: Seq[T]): Seq[T] = a ++ b
}
class SemiGroupMap[U, V] extends Semigroup[Map[U,V]] {
override def combine(a: Map[U, V], b: Map[U, V]): Map[U, V] = a ++ b
}
class SemiGroupNumber[@specialized (Int, Double, Float, Long) T](implicit numeric: Numeric[T]) extends Semigroup[T] {
override def combine(a: T, b: T): T = numeric.plus(a, b)
}
object SemiGroupImplicitTypes {
implicit def numberSemiGroup[T](implicit numeric: Numeric[T]) = new SemiGroupNumber[T]()
implicit def listSemiGroup[T] = new SemiGroupList[T]()
implicit def mapSemiGroup[U,V] = new SemiGroupMap[U,V]()
implicit def seqSemiGroup[U] = new SemiGroupSeq[U]()
}
import SemiGroupImplicitTypes._
SemiGroup[Int](1,2)
SemiGroup[List[Int]](List[Int](1,2,3), List(2,3,5))
The modified version of the implementation I implemented by using def's.
Upvotes: 0
Reputation: 629
You need to implement defs with type parameters:
object SemiGroupImplicitTypes {
implicit object IntSemiGroup extends SemiGroupNumber[Int]
implicit object LongSemiGroup extends SemiGroupNumber[Long]
implicit object DoubleSemiGroup extends SemiGroupNumber[Double]
implicit object FloatSemiGroup extends SemiGroupNumber[Float]
implicit def listSemiGroup[T]: Semigroup[List[T]] = new SemiGroupList[T]
}
Upvotes: 1