Vinothkumar Raman
Vinothkumar Raman

Reputation: 301

Why is this scala code not inferring type?

I am building a aggregation framework with some code which looks like this

trait Aggregate[T <: Aggregate[T, K], K] { self: T =>
  def plus(another: T): T

  def show: K
}

I have couple of aggregations like this,

case class Count(value: Long = 1) extends Aggregate[Count, Long] {
  def plus(another: Count) = Count(value + another.value)

  def show = value
}

Once i define a aggregation which is like this,

case class By[T <: Aggregate[T, K], K, G](values: HashMap[G, T]) extends Aggregate[By[T, K, G], Map[G, K]] {
  override def plus(another: By[T, K, G]): By[T, K, G] = By(values.merged(another.values){case ((k1,v1), (k2,v2)) => (k1, v1 plus v2)})

  override def show: Map[G, K] = values.map{case (k,v) => k -> v.show}
}

object By {
  def apply[T <: Aggregate[T,K], K, G](key:G, value:T):By[T, K, G] = By(HashMap(key -> value))
}

I cannot write something like this

By("key1", Count(100))

Instead i had to write this

By[Count, Long, String]("key1", Count(100))

Since its not figuring out the Long part, I hate to specify those types, is there a cleaner way to achieve that?

Upvotes: 9

Views: 723

Answers (2)

Paul Snively
Paul Snively

Reputation: 106

I suggest using Monoid and Show type classes. You may even want to use kittens (sorry, don't have enough rep to add another link; just Google "scala kittens derivation") to automatically derive the Monoid and Show instances for your case classes.

Upvotes: 4

Alvaro Carrasco
Alvaro Carrasco

Reputation: 6182

Trick I learned:

object By {
  def apply[T <: Aggregate[T,K], K, G](key:G, value:T with Aggregate[T,K]):By[T, K, G] = By(HashMap(key -> value))
}

The with Aggregate[T,K] refinement somehow helps the compiler figure out the types.

Upvotes: 4

Related Questions