Logo Questions Linux Laravel Mysql Ubuntu Git Menu
 

Why is this scala code not inferring type?

Tags:

scala

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?

like image 840
Vinothkumar Raman Avatar asked Sep 09 '16 19:09

Vinothkumar Raman


People also ask

Does Scala support type inference?

The Scala compiler can often infer the type of an expression so you don't have to declare it explicitly.

What would be the type inferred by Scala compiler for variable?

Scala compiler can automatically infer types of each variable declared. If the value of a variable is declared in double-quotes it will automatically be inferred as String. Also, the compiler can infer any value in a single quote is inferred as Char.

What does => mean in Scala?

=> is syntactic sugar for creating instances of functions. Recall that every function in scala is an instance of a class. For example, the type Int => String , is equivalent to the type Function1[Int,String] i.e. a function that takes an argument of type Int and returns a String .


2 Answers

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.

like image 174
Alvaro Carrasco Avatar answered Oct 21 '22 09:10

Alvaro Carrasco


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.

like image 4
Paul Snively Avatar answered Oct 21 '22 10:10

Paul Snively