Scala:有问题的类型推断?

标签 scala type-inference

以下是我的原始代码的简化版本,使事情变得更简单(抱歉还是有点复杂):

trait BuilderBase
trait MessageBase {
  type Builder <: BuilderBase
}
class SomeMessage extends MessageBase {
  type Builder = SomeMessage.Builder
}
object SomeMessage {
  class Builder extends BuilderBase
}
class Covariant[+T]
class NonCovariant[T]
def func[T <: MessageBase](value: Covariant[T]): Covariant[T#Builder] = null

val message: Covariant[SomeMessage] = null
val result: Covariant[SomeMessage.Builder] = func(message)

最后一行编译失败,出现错误 func(→ message ← here) :

type mismatch; found : Covariant[SomeMessage] required: Covariant[SomeMessage.type]



func肯定是取了MessageBase的子类T的Covariant的参数,需要的是Covariant[SomeMessage]而不是Covariant[SomeMessage.type],因为SomeMessage.type(伴生对象SomeMessage的类型)不符合MessageBase。

奇怪的是,如果没有类型注释,错误就会消失,比如,val result = func(message) ,并且结果的类型与含义完全相同:Covariant[SomeMessage.Builder]。所以它只是因为正确的类型注释而失败。这是一个错误吗?

另一个线索是,当所有协变都被非协变替换时,这不会发生。所以它可能以某种方式与协方差有关。任何建议或帮助将不胜感激。

我知道一些小的调整可以解决这个特定问题,例如简单地省略类型注释可能是其中之一。但是,如果我能获得更多关于编译器中真正发生的事情的线索,例如通过为其提供一些命令行选项,那将非常有帮助。

最佳答案

我也不知道原因,但为了给@AssafMendelson 的答案提供一个轻微的替代方案,以下也有效:

trait BuilderBase

trait MessageBase {
  type Builder <: BuilderBase
}
class SomeMessage extends MessageBase {
  type Builder = BuilderBase {}
}

class Covariant[+T]
class NonCovariant[T]
def func[T <: MessageBase](value: Covariant[T]): Covariant[T#Builder] = null

val message: Covariant[SomeMessage] = null
val result: Covariant[SomeMessage#Builder] = func(message)

所以基本上不是在伴随对象中定义类,只需在类中定义它

关于Scala:有问题的类型推断?,我们在Stack Overflow上找到一个类似的问题: https://stackoverflow.com/questions/43524827/

相关文章:

scala - Spark : Get max consecutive decrease in value

scala - 如何缓存 sbt TaskKey 的结果?

javascript - TypeScript 类型推断 - 函数的通用对象

templates - D 中的结构体参数推导

java - 如何使用 ScalaCheck 测试 Java 程序?

scala,喷雾,akka - java.lang.OutOfMemoryError : unable to create new native thread

scala - 在公共(public)/开源 Scala API 中使用 Try 或 Either 进行错误处理是否存在问题?

java - 为什么在使用有界类型参数时需要强制转换

java - 为什么这个分支会中断类型推断?

java - 为什么 Java 泛型类型推断会在链式方法调用中中断?