Scala map&;平面图
为什么映射函数是正确的而平面映射是错误的?唯一的区别是map有一个参数(f:a=>B),而flatmap有一个参数(f:a=>E,B中的任意一个),编译器认为E是一个逆变位置。既然f:A=>B也是一个参数,为什么编译器不抱怨A是一个相反的位置。map和flatmap都需要一个参数,我记得一个参数是一个逆变位置,我只是不明白为什么map工作而flatmap不工作Scala map&;平面图,scala,Scala,为什么映射函数是正确的而平面映射是错误的?唯一的区别是map有一个参数(f:a=>B),而flatmap有一个参数(f:a=>E,B中的任意一个),编译器认为E是一个逆变位置。既然f:A=>B也是一个参数,为什么编译器不抱怨A是一个相反的位置。map和flatmap都需要一个参数,我记得一个参数是一个逆变位置,我只是不明白为什么map工作而flatmap不工作 object test { import scala.{Option=>_,Either=>_,_} sealed
object test {
import scala.{Option=>_,Either=>_,_}
sealed trait Either[+E,+A]{
def map[B](f:A=>B):Either[E,B]= this match {
case Left(e)=>Left(e)
case Right(a)=>Right(f(a))
}
def flatMap[B](f: A=>Either[E,B]):Either[E,B] = this match {
case Left(e)=>Left(e)
case Right(a)=>f(a)
}
}
case class Right[+A](a:A) extends Either[Nothing,A]
case class Left[+E](e:E) extends Either[E,Nothing]
}
A=>B
具有类型函数[-A,+B]
因此,对于所有函数,参数都是逆变的,返回类型是协变的。因此,我们可以做到以下几点:
N extends M
Y extends X
val a : M=>Y = ...
val b : N=>X = a
val x:X = b(new N)
但是当我们嵌套我们的函数时呢
(A=>B)=>(C=>D)
现在A=>B
处于逆变位置,A
处于逆变位置内的逆变位置。这是什么意思?在这之前,我们可以使用A
的超类型来代替A
。在我们的示例中,我们有一个以N
为参数的函数,但我们给它一个以M
为参数的函数,这是N
的超类型
让我们用我们的函数=>尝试一下
def f(g: (M=>Y)=>(N=>X)) {...}
val x:(N=>X)=>(M=>Y) = ...
f(x) // this works
所以在逆变位置的东西,我们可以给出一个超型。但是在相反的位置,我们可以使用子类型。所以反方差等于协方差
在您的示例
map
中,您将协变类型a
用于反变位置,使其变为协变,从而编译正常
在flatMap
中,使用A
的方式相同,但协变的B
用于逆变位置。这就是问题所在
要解决此问题,请使用:
def flatMap[F>:E,B](f:A=>Either[F,B]):Either[F,B]