Scala 制作逆变物体

Scala 制作逆变物体,scala,contravariance,Scala,Contravariance,我正在尝试创建一个反向类: class ContraObj[-T] { var item: T = _ // initialize `item` to "some" T value def replace(t: T) = (item = t) } 但出现以下编译时错误: [error] .../ContraObj.scala:4: contravariant type T occurs in covariant position in type

我正在尝试创建一个反向类:

class ContraObj[-T] {
  var item: T = _                 // initialize `item` to "some" T value
  def replace(t: T) = (item = t) 
}
但出现以下编译时错误:

[error] .../ContraObj.scala:4: contravariant type T occurs in covariant 
   position in type => T of method item
[error]   var item: T = _
[error]       ^

如何解决此错误?

您需要考虑反向变化的含义。也就是说,它意味着什么以及由此产生的约束。因此,

trait Foo[-T]{
  def stuff(t: T): T
}
现在想想在以下上下文中这意味着什么:

def action(that: Foo[Int]) = that.stuff(1)
如果我给它一个
Foo[Any]
。这是否意味着,如果我希望下面的定义将
Int
返回给我,那么它将成功

def action(that: Foo[Int]): Int = that.stuff(1)

它不能,不是吗?这是因为您定义的是一个函数,函数的签名是
函数[-T,+R]
,您试图将其定义为
函数[-T,-T]

你需要想想逆变是什么意思。也就是说,它意味着什么以及由此产生的约束。因此,

trait Foo[-T]{
  def stuff(t: T): T
}
现在想想在以下上下文中这意味着什么:

def action(that: Foo[Int]) = that.stuff(1)
如果我给它一个
Foo[Any]
。这是否意味着,如果我希望下面的定义将
Int
返回给我,那么它将成功

def action(that: Foo[Int]): Int = that.stuff(1)


它不能,不是吗?这是因为您定义的是一个函数,函数的签名是
函数[-T,+R]
,您试图将其定义为
函数[-T,-T]

逆变类型将是输入,而不是输出。你能解释一下原因吗?更多的背景可以在Twitter的Scala学校找到,从“逆变似乎很奇怪。何时使用?有点奇怪!”,@KevinMeredith,你必须理解函数在其输入上是协变的,但在输出上是逆变的。例如,请看。此外,请将此与“.@KevinMeredith”Why”联系起来,这真的超出了我们的知识范围。如果您想一想
函数1
,以及它对协变和逆变参数的意义,它是有意义的。我很确定集合论或范畴论和某种逻辑可以解释为什么,但我自己从来没有研究过。逆变类型是输入,而不是输出。你能解释一下为什么吗?更多的背景可以在Twitter的Scala学校找到,从“逆变似乎很奇怪。什么时候使用它?有点奇怪!”,@KevinMeredith,你必须理解函数在输入端是协变的,但在输出端是逆变的。例如,请看。此外,请将此与“.@KevinMeredith”Why”联系起来,这真的超出了我们的知识范围。如果您想一想
函数1
,以及它对协变和逆变参数的意义,它是有意义的。我很确定集合论或范畴论和某种逻辑可以解释为什么,但我自己从来没有研究过。所以,在你的例子中,
def action(that:Foo[Int]):Int=that.stuff(1)
Int
T
的一个实例,它是反变的<代码>动作定义为
函数[-T,-T]
,因为
Int
既是
Foo[]
的类型参数,也是
返回类型
?我用-,编译了它,但是为什么我想要
AnyVal
-它不是类型安全的,不是吗?@KevinMeredith在您的示例中,您实际上希望
action
具有以下内容:
def action[R](that:Foo[Int,R]):R=that.stuff(1)
来捕获您正在寻找的内容。那里的
R
可以以任何方式变化,应该从类型系统中推断出来。谢谢,@wheaties。我对你的答案有了进一步的了解,但我仍然无法用1-2句话来解释为什么
函数
[-R,+t]
@KevinMeredith是有意义的。我知道这种情况有一个很好的理论原因(参数是接受者)。除了“这才有意义”之外,我从来没有认真考虑过它推理路线。问得好。Martin Odersky在Scala方差讲座中的Coursera Functional Programming Principles中给出了一个很好的解释,解释了为什么
函数是
[-R,+T]
,在你的例子中,
def action(that:Foo[Int]):Int=that.stuff(1)
Int
T
的一个例子,这是相反的<代码>动作
定义为
函数[-T,-T]
,因为
Int
既是
Foo[]
的类型参数,也是
返回类型
?我用-,编译了它,但是为什么我想要
AnyVal
-它不是类型安全的,不是吗?@KevinMeredith在您的示例中,您实际上希望
action
具有以下内容:
def action[R](that:Foo[Int,R]):R=that.stuff(1)
来捕获您正在寻找的内容。那里的
R
可以以任何方式变化,应该从类型系统中推断出来。谢谢,@wheaties。我对你的答案有了进一步的了解,但我仍然无法用1-2句话来解释为什么
函数
[-R,+t]
@KevinMeredith是有意义的。我知道这种情况有一个很好的理论原因(参数是接受者)。除了“这才有意义”之外,我从来没有认真考虑过它推理路线。问得好。Martin Odersky在Scala方差讲座()中的函数编程原理课程中对为什么
函数
[-R,+T]
给出了很好的解释