如何阅读这个flatMap代码?

时间:2015-12-02 02:14:19

标签: scala functional-programming

我无法破译以下功能。特别是flatMap线 - 'aa'和'bb;来自的变量,以及如何执行?也许如果有人能用语言解释这段代码发生了什么,那将会有所帮助。我只是在努力学习如何阅读这种语法。

def map2[EE >: E, B, C](b: Either[EE, B])(f: (A, B) => C): Either[EE, C] = 
    this flatMap(aa => b map (bb => f(aa, bb)))

这是flatMap函数:

 def flatMap[EE >: E, B](f: A => Either[EE, B]): Either[EE, B] = this match {
   case Right(r) => f(r)
   case Left(e) => Left(e)
 }

和地图:

def map[B](f: A => B): Either[E, B] = this match {
   case Right(r) => Right(f(r))
   case Left(e) => Left(e)
 }

1 个答案:

答案 0 :(得分:3)

看起来所有这些函数都是为Either类定义的。要么处于两种状态,要么处于两种状态。 - 右 - 正确的值和左,它解释了屁股错误。

让我们从地图定义出发。我们有A类参数化。 map 接受函数转换类型A到B.因此map函数检查value是否为Right然后它将给定函数f应用于Right值,用Right包装并返回。如果错误则返回错误。

Right[String, Int](4).map(_*3)      // gives Right(12)
Left[String, Int]("error").map(_*3) // gives Left("error")

flatMap 类似于map,但是接受函数转换类型A到任何一个右类型B,所以不像map我们不需要包装正确的值

Right[String, Int](5).flatMap(item => Right(item*3))        //gives Right(15)
Left[String, Int]("error").flatMap(item => Right(item*3))   //gives Left("error")

根据定义, map2 采用E和b的函数,将类型A和B的值转换为某个第三个值C,并返回包含在Either中的结果。让我们仔细看看它是如何实现的。

this.flatMap(aa => b map (bb => f(aa, bb)))       

让我们用flatMap的定义重写它:

this.match {
  case Right(r) => b.map (bb => f(r, bb))
  case Left(e) => Left(e)
}

并应用地图:

this.match {
  case Right(r) => {
    b match {
      case Right(br) => Right(f(r, br))
      case Left(be) => Left(be)
    }
  }
  case Left(e) => Left(e)
}

所以有三条路径:

if right a and right b then apply function(a,b)
if right a and error b then error(b)
if error a then error a

示例:

Right(7).map2(Right(4)){case (a,b) => a*b} // gives Right(28)
Right(7).map2(Left[String, Int]("failed")){case (a,b) => a*b}  //gives Left("failed")
Left[String, Int]("error").map2(Left[String, Int]("failed")){case (a,b) => a*b}  //gives Left("error")

编辑:内部功能说明

您必须传递给类型为

的flatMap函数
A => Either[EE, C]

这意味着"采用类型A的参数并将其转换为类型的结果[EE,C]"

所以你可以定义:

def map2[EE >: E, B, C](b: Either[EE, B])(f: (A, B) => C): Either[EE, C] = {     
  def func(aa:A):Either[EE, C] = {
     b map (bb => f(aa, bb))
  }
  this flatMap(func)
}