Scala 类型系统。 "Deferred" 类型参数。为什么这有效?

Scala typesystem. "Deferred" type parameter. Why this works?

我一直在写一些代码,它引导我:

trait SplitStrategy[E] {
  def apply(seq: Seq[E]): Seq[(Int, Seq[E])]
}

object SplitByConsecutiveElements {
  def apply[E](consecutiveValue: Seq[E] => E): SplitByConsecutiveElements[E] = new SplitByConsecutiveElements(consecutiveValue)
  def withConsecutiveValueAsTheHighestCount[E]: SplitByConsecutiveElements[E] = {
    val consecutiveValue: Seq[E] => E = seq => {
      seq.foldLeft(Map.empty[E, Int].withDefaultValue(0)) {
        case (m, v) => m.updated(v, m(v) + 1)
      }.maxBy(_._2)._1
    }
    SplitByConsecutiveElements(consecutiveValue)
  }

  def main(args: Array[String]): Unit = {
    println(SplitByConsecutiveElements.withConsecutiveValueAsTheHighestCount.apply(Seq(1, 1, 2, 1, 2)))
  }

}

class SplitByConsecutiveElements[E](val consecutiveValue: Seq[E] => E) extends SplitStrategy[E] {
  override def apply(seq: Seq[E]): Seq[(Int, Seq[E])] = splitSequenceBySequenceOfElements(seq, consecutiveValue(seq))
  private def splitSequenceBySequenceOfElements[E](seq: Seq[E], consecutiveValue: E): Seq[(Int, Seq[E])] = {
    // This is just a dummy operation, not the real algorithm
    Seq((0, seq.filter(consecutiveValue == _)))
  }
}

如果您查看 "main" 方法,您会看到我调用了 SplitByConsecutiveElements.withConsecutiveValueAsTheHighestCount,然后将其应用于 Int 的序列。起初,我以为它不会编译。但它确实可以编译并正常工作。 我让它不起作用的理由是,在调用 SplitByConsecutiveElements.withConsecutiveValueAsTheHighestCount 时,我正在创建一个未知类型参数 ESplitByConsecutiveElements[E]。然后我应用 SplitByConsecutiveElements[E].someMethod,其中 E 是已知的,但我已经创建了 SplitByConsecutiveElements[E] 的实例,而不是 SplitByConsecutiveElements[Int] 的实例。为什么这行得通?它就像编译时的 class transofrms 本身?

我现在脑子里乱七八糟的,希望我把我的担心表达好。

它起作用的原因有两个:

1) JVM 上的泛型被删除,因此可以在不知道 E 的情况下创建 SplitStrategy[E] 的实例。所以不需要 "transform the class at compile time".

2) 即使我们在一个没有删除泛型类型的平台上(比如,C# 的 CLR),这段代码仍然可以工作。

编译器尝试根据上下文推断 E in SplitStrategy[E] 以使整个表达式有效。在你的情况下,它成功地猜测 EInt.