Scala中的协方差与协方差 [英] Contravariance vs Covariance in Scala

查看:232
本文介绍了Scala中的协方差与协方差的处理方法,对大家解决问题具有一定的参考价值,需要的朋友们下面随着小编来一起学习吧!

问题描述

我刚刚学习了Scala。现在,我对Convarivariance和协方差感到困惑。

I just learned Scala. Now I am confused about Contravariance and Covariance.

来自此页面,我从下面中学到了一些东西:

From this page, I learned something below:

协方差

也许子类型化的最明显特征是能够用表达式中的较窄类型的值替换较宽类型的值。例如,假设我有一些类型 Real Integer< ;: Real 和一些不相关的类型布尔值。我可以定义一个函数 is_positive :: Real->布尔值,它对 Real 值起作用,但是我也可以将此函数应用于类型为 Integer (或 Real 的任何其他子类型)。用较窄的(后代)类型替换较宽的(祖先)类型称为协方差协方差的概念使我们能够编写通用代码,并且在推理面向对象编程语言中的继承和功能语言中的多态性时具有无价的意义。

Perhaps the most obvious feature of subtyping is the ability to replace a value of a wider type with a value of a narrower type in an expression. For example, suppose I have some types Real, Integer <: Real, and some unrelated type Boolean. I can define a function is_positive :: Real -> Boolean which operates on Real values, but I can also apply this function to values of type Integer (or any other subtype of Real). This replacement of wider (ancestor) types with narrower (descendant) types is called covariance. The concept of covariance allows us to write generic code and is invaluable when reasoning about inheritance in object-oriented programming languages and polymorphism in functional languages.

但是,我还从其他地方看到了东西:

However, I also saw something from somewhere else:

scala> class Animal
    defined class Animal

scala> class Dog extends Animal
    defined class Dog

scala> class Beagle extends Dog
    defined class Beagle

scala> def foo(x: List[Dog]) = x
    foo: (x: List[Dog])List[Dog] // Given a List[Dog], just returns it
     

scala> val an: List[Animal] = foo(List(new Beagle))
    an: List[Animal] = List(Beagle@284a6c0)

foo 的参数 x 变量;它期望一个类型为 List [Dog] 的参数,但是我们给它一个 List [Beagle] ,这没关系

Parameter x of foo is contravariant; it expects an argument of type List[Dog], but we give it a List[Beagle], and that's okay

[我认为第二个示例也应证明协方差。因为从第一个示例中,我了解到将此函数应用于 Integer 类型的值(或任何其他 Real )。因此,相应地,在这里我们将此函数应用于 List [Beagle] (或 List [Dog] )。但是令我惊讶的是,第二个例子证明了协方差]

[What I think is the second example should also prove Covariance. Because from the first example, I learned that "apply this function to values of type Integer (or any other subtype of Real)". So correspondingly, here we apply this function to values of type List[Beagle](or any other subtype of List[Dog]). But to my surprise, the second example proves Cotravariance]

我认为两个人在谈论同一件事,但是一个证明协方差和其他协方差。我还看到了来自SO的问题。但是我还是很困惑。我是否错过了某些事情,或者其中一个示例是错误的?

I think two are talking the same thing, but one proves Covariance and the other Contravariance. I also saw this question from SO. However I am still confused. Did I miss something or one of the examples is wrong?

推荐答案

您可以传递 List [ Beagle] 到期望 List [Dog] 的函数与函数的无关性,仍然是因为List是协变的,并且 List [Beagle] List [Dog]

That you can pass a List[Beagle] to a function expecting a List[Dog] is nothing to do with contravariance of functions, it is still because List is covariant and that List[Beagle] is a List[Dog].

反而说您有一个函数:

def countDogsLegs(dogs: List[Dog], legCountFunction: Dog => Int): Int

此功能计算狗列表中的所有腿。它具有接受狗的函数并返回表示该狗有多少条腿的整数。

This function counts all the legs in a list of dogs. It takes a function that accepts a dog and returns an int representing how many legs this dog has.

此外,我们说我们有一个函数:

Furthermore lets say we have a function:

def countLegsOfAnyAnimal(a: Animal): Int

可以计算任何动物的腿。我们可以将 countLegsOfAnyAnimal 函数传递给 countDogsLegs 函数作为函数参数,这是因为如果这东西可以任何动物的腿,它都可以数狗的腿,因为狗是动物,这是因为功能是互变的。

that can count the legs of any animal. We can pass our countLegsOfAnyAnimal function to our countDogsLegs function as the function argument, this is because if this thing can count the legs of any animal, it can count legs of dogs, because dogs are animals, this is because functions are contravariant.

如果您查看 Function1 (一个参数的函数)的定义,则为

If you look at the definition of Function1 (functions of one parameter), it is

trait Function1[-A, +B]

这是因为它们在输入上是协变的,在输出上是协变的。所以 Function1 [Animal,Int]< ;: Function1 [Dog,Int] 因为 Dog< ;: Animal

That is that they are contravariant on their input and covariant on their output. So Function1[Animal,Int] <: Function1[Dog,Int] since Dog <: Animal

这篇关于Scala中的协方差与协方差的文章就介绍到这了,希望我们推荐的答案对大家有所帮助,也希望大家多多支持IT屋!

查看全文
登录 关闭
扫码关注1秒登录
发送“验证码”获取 | 15天全站免登陆