Scala泛型实现的奇怪错误

时间:2017-11-22 20:17:01

标签: scala

我有以下特点:

trait SomeTrait {
  def doSomething[V](msg: Message[V]): Message[V]
}

Message [V]是一个案例类如下:

case class Message[V](elems: Map[String, V])

我现在有一个调用doSomething方法的方法如下:

  val someWork = new SomeTrait {
    override def doSomething[Int](msg: Message[Int]): Message[Int] = {
      msg.copy(elems = msg.elems.map {
        case (k, v) => (k, v + 1) // It fails here!!!
      })
    }
  }

我得到一个奇怪的编译器错误说:

Error:(16, 32) type mismatch;
 found   : Int(1)
 required: String
Error occurred in an application involving default arguments.
        case (k, v) => (k, v + 1)

我在某个地方傻了吗?

2 个答案:

答案 0 :(得分:3)

注意:您的Int不是scala Int。您将Scala [Int]隐藏在泛型类型名称后面 - 您所编写的内容看起来像是C ++中的模板特化,但是泛型在Scala中不能以这种方式工作。在代码中将[XXX]替换为V时,您将收到相同的错误。

覆盖方法时无法更改类型签名。由于特征承诺您接受任何类型case class Message[V](elems: Map[String, V]) trait SomeTrait { def doSomething[V: MapValue](msg: Message[V]) } trait MapValue[V] { def map(v: V): V } implicit object MapValueInt extends MapValue[Int] { def map(v: Int) = v + 1 } val someWork = new SomeTrait { override def doSomething[X: MapValue](msg: Message[X]) = { val evidence = implicitly[MapValue[X]] msg.elems.map { case (k, v) => k -> evidence.map(v) } } } 而没有任何约束,因此实现需要满足此承诺。

C ++ - 就像使用type classes一样可以实现专业化 - 您通过承诺将根据需要提供专门的实现来扩展您的合同:

{{1}}

答案 1 :(得分:1)

@Suma所说的......在这种情况下,您也可以参数化特征而不是方法。它不那么通用,但有点简单:

trait SomeTrait[V] {
  def doSomething(msg: Message[V]): Message[V]
}

val someWork = new SomeTrait[Int] {
  def doSomething(msg: Message[Int]) = msg.copy(msg.elems.mapValues(_ + 1) 
}