为什么Scala不能在此示例中推断出类型参数?

Jay*_*rod 8 generics types scala type-inference

假设我有两个类,Input并且Output,其被设计为连接到彼此.Output生成某种类型的值,并使用Input它们.

class Input[T] {
  var output: Option[Output[_ <: T]] = None
}
class Output[T] {
  var input: Option[Input[_ >: T]] = None
}
Run Code Online (Sandbox Code Playgroud)

只要类型参数是类型参数的超类型,Input并且Output对和不对同一类值进行操作就没关系.请注意,两个类中的type参数都是不变的; 在真实版本中,它用于共同和逆变位置.InputOutput

我在connect其他地方有一个方法,它在Input/ Outputpair 之间建立一个链接:

def connect[T](output: Output[T], input: Input[_ >: T]) = {
  output.input = Some(input)
  input.output = Some(output)
}
Run Code Online (Sandbox Code Playgroud)

如果我按如下方式调用此方法,则会出现类型错误:

val out = new Output[String]
val in = new Input[AnyRef]
connect(out, in)
Run Code Online (Sandbox Code Playgroud)

错误是:

test.scala:17: error: type mismatch;
 found   : Output[String]
 required: Output[AnyRef]
  connect(out, in)
          ^
Run Code Online (Sandbox Code Playgroud)

我可以通过写出类型参数来解决这个问题(在这种情况下,我会写connect[String],但我认为编译器应该能够为我解决这个问题.如何更改connect方法以便自动推断类型参数?


编辑:现在,我已经做connect了一个方法,Output所以它自动获取类型参数.这也有额外的好处,我可以使用中缀符号out connect in,但设计感觉有点尴尬.

我仍然对编译器为什么会出现这种行为感兴趣.我觉得它应该能够推断出类型参数.这实际上是否符合规定?

psp*_*psp 6

如果使用多个参数列表,有时会得到更好的结果:

def connect[T](output: Output[T])(input: Input[_ >: T]) = {
  output.input = Some(input)
  input.output = Some(output)
}

connect(out)(in)
Run Code Online (Sandbox Code Playgroud)

......确实在这种情况下,它有效.

  • 遗憾的是,类型推断器并不是规范的,有时也不是确定性的. (6认同)
  • 你能扩展一下为什么会这样吗?*"有时会得到更好的结果"*听起来不是很确定! (3认同)