Clarifying contravariance nature of the return type of a function as parameter a function of an outer convariant container

﹥>﹥吖頭↗ 提交于 2021-01-01 09:40:48

问题


In Option we have

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
    }

In Either we have:

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

I understand what is going and why, a rather extended example could be this

OrElse( { Option[B]}).map{....} If B is such that A :> B, then if Some(a) you get Some(a).map(f:B => ???) then Kaboom

generally speaking i think i am ok with variance. What i did not see or figure out because that is not what the simple example of co-variance and contravariance explain as use cases, and would like to confirm here:

The return type of a function as parameter is checked for variance position of the outer container.

Typically the example would be

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

We are then explained, can't do, contra-variance position for A. I will not re-do to full explanation as to why. Let's assume we all understand it.

What is not usually explained is:

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

It is not just taking a parameter of type A, but also taking any function parameter that return that A. The compiler goes at length to check that too. I wonder if it stops here, or if it is anything that can produce an A, as parameter to a function of the Container.


回答1:


Your understanding is completely correct. To be honest, I am not sure what exactly is the question, but I will assume it's - which places does compiler check in a case such as:

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

And the answer is - all of them.

So when compiler sees trait Container[+A], it will check the body of that Container for all occurrences of A, to see if they are in:

  • parameter position (which brings the contravariant requirement)
  • return type position (covariant requirement)
  • both (invariant requirement)
  • neither (so-called phantom variance).

In case of Container[+A], it will require that all occurrences of A are in covariant position, meaning that it will have a problem with String => A.

It's as simple as that. Doesn't matter if it's an "inner function" or an "outer function".



来源:https://stackoverflow.com/questions/64969602/clarifying-contravariance-nature-of-the-return-type-of-a-function-as-parameter-a

易学教程内所有资源均来自网络或用户发布的内容,如有违反法律规定的内容欢迎反馈
该文章没有解决你所遇到的问题?点击提问,说说你的问题,让更多的人一起探讨吧!