繁体   English   中英

Scala List地图功能的差异

[英]Variance of Scala List map function

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

假设我们有以下类:

class A  
class B extends A

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

但我也可以使用f: A => C ,它是f: B => C的子类
这完全有道理。

我目前感到困惑的是, map函数应该只接受原始函数的超类的函数(因为函数的参数是相反的),这不适用于我给出的示例。

我知道我的逻辑有问题,我想启发一下。

您的错误在于map(f: A => C)应该只接受A => C超类的函数。

实际上, map可以接受A => C的子类的任何函数。

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

的协方差AList[A]仅告诉你,只要一个List[A]是必需的,则可以提供一个List[B]只要B <: A

或者,用更简单的话来说: List[B]可以被视为List[A]的子类。

我整理了一个小例子来解释这两种行为:

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)

试试看!

我希望这有帮助。

正如您已经怀疑的那样,您在这里混淆了一些事情。

一方面,您有一个List[+A] ,它告诉我们有关List[A]List[B]之间关系的一些信息,给定AB之间的关系。 这样的事实List是协变A只是意味着List[B] <: List[A]B <: A ,你知道已经知道了。

另一方面, List公开了一个方法map以更改其“内容”。 此方法实际上并不关心List[A] ,而仅关心A s,因此List的方差在这里无关紧要。 令您感到困惑的是,确实有一些子类型需要考虑: map接受一个参数(在这种情况下为A => C ,但实际上并不相关),并且像往常一样,对于方法和函数,您始终可以用其子类型的任何内容替换其参数。 在您的特定情况下,只要AcceptedType <: Function1[A,C] ,任何AcceptedType都可以。 这里重要的方差是Function的,而不是List的。

暂无
暂无

声明:本站的技术帖子网页,遵循CC BY-SA 4.0协议,如果您需要转载,请注明本站网址或者原文地址。任何问题请咨询:yoyou2525@163.com.

 
粤ICP备18138465号  © 2020-2024 STACKOOM.COM