为什么这个scala代码不能推断类型?

时间:2016-09-09 19:01:03

标签: scala

我正在使用一些类似

的代码构建聚合框架
trait Aggregate[T <: Aggregate[T, K], K] { self: T =>
  def plus(another: T): T

  def show: K
}

我有几个这样的聚合,

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

  def show = value
}

一旦我定义了这样的聚合,

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))
}

我不能写这样的东西

By("key1", Count(100))

相反,我必须写这个

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

由于它没有找出Long部分,我讨厌指定那些类型,有没有更清晰的方法来实现它?

2 个答案:

答案 0 :(得分:4)

欺骗我学到了:

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))
}

with Aggregate[T,K]细化以某种方式帮助编译器找出类型。

答案 1 :(得分:4)

我建议使用MonoidShow类型类。您甚至可能想要使用小猫(抱歉,没有足够的代表来添加其他链接;只有Google“scala kittens derivation”)来自动派生您的案例类的MonoidShow个实例。