Scala列表映射函数的方差
我有个问题一直困扰着我。 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],它
List[+A]
)
假设我们有这些课程:
class A
class B extends A
List[B]
的map
函数采用函数f:B=>C
但是我也可以使用af: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]
的地方,只要Bmap
像任何函数一样,接受所需参数类型的任何子类型,就可以提供列表[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)