【问题标题】:Clarifying contravariance nature of the return type of a function as parameter a function of an outer convariant container阐明作为参数的函数返回类型的逆变性质是外部协变容器的函数
【发布时间】:2021-03-06 05:42:58
【问题描述】:

在选项中我们有

def getOrElse[B >: A](default: => B): B = this match {
        case None => default
        case Some(a) => a
    }
def orElse[B >: A](obj: => Option[B]): Option[B] = this match {
        case None => obj
        case _ => this
    }

我们有:

def flatMap[EE >: E, B](f: A => Either[EE, B]): Either[EE, B]

我了解发生了什么以及为什么,一个相当扩展的示例可能是这样的

OrElse( { Option[B]}).map{....} 如果 B 满足 A :> B,那么如果 Some(a) 你得到 Some(a).map(f:B => ???) 然后 Kaboom

一般来说,我认为我可以接受差异。我没有看到或弄清楚什么,因为这不是协变和逆变的简单示例作为用例解释的内容,并且想在此确认:

作为参数的函数的返回类型检查外部容器的方差位置。

典型的例子是

Container[+A] {
  def outerfunction[B](value: A): B
}

然后我们解释了,不能做,A 的逆变位置。我不会重新解释为什么。假设我们都理解它。

通常不解释的是:

Container[+A] {
      def outerfunction(f: ??? => A): A
    }

它不仅采用 A 类型的参数,而且还采用任何返回该 A 的函数参数。编译器也会仔细检查。我想知道它是否停在这里,或者它是否可以产生 A,作为 Container 函数的参数。

【问题讨论】:

  • 不确定问题是什么 - WDYM with: " 我想知道它是否停在这里,或者它是否可以产生 A,作为容器函数的参数。" ?
  • 一个函数产生一个 A,但我不知道,另一个容器可以看作是 A 的生产者,例如将 LIST[A] 作为参数传递给 Container [+A] 的函数
  • 虽然我可以直接测试它,但我只是在想也许我可能不会考虑所有情况。
  • 另外我想确认一下,确实是因为参数函数Return A,那个A变成了逆变的。
  • 对不起,我还是不明白你在说什么。但我会尽力而为: 1. 虽然您确实可以将任何协变类型构造函数视为生产者,例如返回 As 的函数,并且它们中的大多数都有一个自然的操作,就像function (甚至它们中的大多数都实现了 function trait) 这并不意味着您总是可以传递协变类的实例,其中函数本身是预期的,但创建 lambda 应该是直截了当(这有意义吗?)

标签: scala generics covariance


【解决方案1】:

你的理解是完全正确的。老实说,我不确定到底是什么问题,但我会假设它是 - 编译器在以下情况下检查哪些地方:

trait Container[+A] {
  def outerfunction(f: String => A): A
}

答案是 - 全部。

因此,当编译器看到trait Container[+A] 时,它会检查Container 的正文中是否出现A,看看它们是否在:

  • 参数位置(带来逆变要求)
  • 返回类型位置(协变要求)
  • 两者(不变的要求)
  • 两者都不是(所谓的phantom variance)。

如果是Container[+A],则要求所有出现的A都处于协变位置,这意味着String => A会有问题。

就这么简单。不管是“内部函数”还是“外部函数”。

【讨论】:

  • 回到这一点。我有另一种情况的案例,这让我重新审视了这一点。用你自己的话来说,为什么编译器会出现String => A 的问题。从 f 的角度来看,A 处于协变位置,但从 Container 的角度来看,情况就不同了。我知道这可能很明显,但还是想用你自己的话来确认一下。
  • 正是你所说的。 A 是函数f 的返回类型,返回类型是一个协变位置。但是整个函数f 是方法outerfunction 的参数,这是一个逆变位置。请注意,函数(与方法不同)不能参数化,因此f 无论如何都不能抱怨。还要注意——这很重要——方差是类的质量,而不是参数的质量。我们说“类 Container 在其类型上是协变的”。如果您将 [+A] 从类移动到方法,使其成为 def outerfunction[A],那么您将无法通过 +- 定义方差。
  • 晶莹剔透!!!感谢您抽出宝贵的时间和额外的小费!!!
猜你喜欢
  • 2017-05-13
  • 1970-01-01
  • 1970-01-01
  • 2011-07-01
  • 2023-02-01
  • 2021-05-24
  • 2020-01-25
  • 1970-01-01
  • 1970-01-01
相关资源
最近更新 更多