Scala列表映射函数的方差

Scala列表映射函数的方差,scala,function,covariance,contravariance,generic-variance,Scala,Function,Covariance,Contravariance,Generic Variance,我有个问题一直困扰着我。 Scala中的列表是协变的(List[+A]) 假设我们有这些课程: class A class B extends A List[B]的map函数采用函数f:B=>C 但是我也可以使用af:a=>C 这是f:B=>C 这完全有道理 我现在感到困惑的是 map函数应该只接受作为原始函数的超类的函数(因为函数在其参数上是逆变的),这在我给出的示例中不适用 我知道我的逻辑有问题,我想开导一下。正如你已经怀疑的那样,你把这里的事情搞混了 一方面,你有一个列表[+a],它

我有个问题一直困扰着我。 Scala中的列表是协变的(
List[+A]

假设我们有这些课程:

class A  
class B extends A
List[B]
map
函数采用函数
f:B=>C

但是我也可以使用a
f:a=>C
这是
f:B=>C

这完全有道理

我现在感到困惑的是
map
函数应该只接受作为原始函数的超类的函数(因为函数在其参数上是逆变的),这在我给出的示例中不适用


我知道我的逻辑有问题,我想开导一下。

正如你已经怀疑的那样,你把这里的事情搞混了


一方面,你有一个
列表[+a]
,它告诉我们
List[a]
List[B]
之间的关系,给定
a
B
之间的关系。
List
A
中是协变的,这一事实仅仅意味着
List[B]您的错误在于假设
map(f:A=>C)
应该只接受作为
A=>C
超类的函数

实际上,
map
将接受属于
a=>C
子类的任何函数

在Scala中,函数参数始终可以是所需类型的子类。


List[A]
A
的协方差仅告诉您,无论何时需要
List[A]
,您都可以提供
List[B]
,只要
B的类型参数的协方差与
map
的参数无关<代码>列表[+T]
只是告诉您,对于每个需要
列表[a]
的地方,只要
B
map
像任何函数一样,接受所需参数类型的任何子类型,就可以提供
列表[B]
。对于
函数[A,C]来说,这两个语句完全不矛盾。
map()
是一个接受类型为X的参数的方法,与所有方法一样,它将接受一个属于X的子类型的参数。X是函数类型的事实不会改变这一点。如果函数在其参数上是反变的,则这与
map()
无关。“接受X或sub-X”规则仍然适用。谢谢您的回答。我不应该提及列表的协方差,因为它与我的问题无关。我基本上对
flatMap
方法[+A,+B]
感到困惑,其中的“B”处于协变位置,这是正常的,在我看来,
flatMap
可以接受带有子类的函数作为参数谢谢你的答案。我不应该提及列表的协方差,因为它与我的问题无关。我基本上对[+A,+B]的平面图方法感到困惑,其中“B”处于协变位置,这是正常的,在我看来,平面图可以接受带有子类的函数作为参数
class A  
class B extends A

// this means: B <: A

val listA: List[A] = List()
val listB: List[B] = List()

// Example 1: List[B] <: List[A]
// Note: Here the List[+T] is our parameter! (Covariance!)

def printListA(list: List[A]): Unit = println(list)

printListA(listA)
printListA(listB)

// Example 2: Function[A, _] <: Function[B, _]
// Note: Here a Function1[-T, +R] is our parameter (Contravariance!)

class C

def fooA(a: A): C = ???
def fooB(b: B): C = ???

listB.map(fooB)
listB.map(fooA)