Scala 将“flatMap”转换为“for comprehension”,使用

Scala 将“flatMap”转换为“for comprehension”,使用,scala,Scala,给定一个[String,Int]: 我可以使用flatMap编写以下代码: 但是,对于理解版,我做错了什么 ifa==100 Leftfoo else Righta是一个[String,Int],而不是LeftProjection或RightProjection,因此它没有map或flatMap。您还需要对其进行投影: for { a <- z.right _ <- (if(a == 100) Left("foo") else Right(a)).right } yi

给定一个[String,Int]:

我可以使用flatMap编写以下代码:

但是,对于理解版,我做错了什么

ifa==100 Leftfoo else Righta是一个[String,Int],而不是LeftProjection或RightProjection,因此它没有map或flatMap。您还需要对其进行投影:

for {
    a <- z.right
    _ <- (if(a == 100) Left("foo") else Right(a)).right
} yield a
该衬里与单衬里的区别在于,单衬里相当于:

for {
    a <- z.right
} yield (if(a == 100) Left("foo") else Right(a))
。。它的末尾没有额外的映射。

ifa==100 Leftfoo else Righta是一个[String,Int],而不是LeftProjection或RightProjection,因此它没有map或flatMap。您还需要对其进行投影:

for {
    a <- z.right
    _ <- (if(a == 100) Left("foo") else Right(a)).right
} yield a
该衬里与单衬里的区别在于,单衬里相当于:

for {
    a <- z.right
} yield (if(a == 100) Left("foo") else Right(a))

。。最后没有额外的地图。

我认为这个问题的公认答案现在已经过时了

自Scala2.12以来,默认情况下,这两种方法都是右偏的。 因此,要么定义了map和flatMap

/** Binds the given function across `Left`.
 *
 *  {{{
 *  Left(12).left.flatMap(x => Left("scala")) // Left("scala")
 *  Right(12).left.flatMap(x => Left("scala")) // Right(12)
 *  }}}
 *  @param f The function to bind across `Left`.
 */
def flatMap[A1, B1 >: B](f: A => Either[A1, B1]): Either[A1, B1] = e match {
  case Left(a) => f(a)
  case _       => e.asInstanceOf[Either[A1, B1]]
}

/** Maps the function argument through `Left`.
 *
 *  {{{
 *  Left(12).left.map(_ + 2) // Left(14)
 *  Right[Int, Int](12).left.map(_ + 2) // Right(12)
 *  }}}
 */
def map[A1](f: A => A1): Either[A1, B] = e match {
  case Left(a) => Left(f(a))
  case _       => e.asInstanceOf[Either[A1, B]]
}
因此,您不必使用RightProjection,因为默认情况下这两个选项都是右偏的。所以下面的代码是有效的

  val z: Either[String, Int] = Right(100)

  val ans = for {
    a <- z
    _ <- if (a == 100) Left("foo") else Right(a)
  } yield a

希望这能有所帮助。

我认为这个问题的公认答案现在已经过时了

自Scala2.12以来,默认情况下,这两种方法都是右偏的。 因此,要么定义了map和flatMap

/** Binds the given function across `Left`.
 *
 *  {{{
 *  Left(12).left.flatMap(x => Left("scala")) // Left("scala")
 *  Right(12).left.flatMap(x => Left("scala")) // Right(12)
 *  }}}
 *  @param f The function to bind across `Left`.
 */
def flatMap[A1, B1 >: B](f: A => Either[A1, B1]): Either[A1, B1] = e match {
  case Left(a) => f(a)
  case _       => e.asInstanceOf[Either[A1, B1]]
}

/** Maps the function argument through `Left`.
 *
 *  {{{
 *  Left(12).left.map(_ + 2) // Left(14)
 *  Right[Int, Int](12).left.map(_ + 2) // Right(12)
 *  }}}
 */
def map[A1](f: A => A1): Either[A1, B] = e match {
  case Left(a) => Left(f(a))
  case _       => e.asInstanceOf[Either[A1, B]]
}
因此,您不必使用RightProjection,因为默认情况下这两个选项都是右偏的。所以下面的代码是有效的

  val z: Either[String, Int] = Right(100)

  val ans = for {
    a <- z
    _ <- if (a == 100) Left("foo") else Right(a)
  } yield a
希望这有帮助