避免嵌套以便使用monadic操作进行理解

时间:2014-03-13 00:01:37

标签: scala functional-programming scalaz

我尝试实现以下内容,其中ab都属于Option[List[Int]]类型:

val a = List(1, 2, 3).some
val b = for {
  xs <- a
  el <- xs
} yield el + 1

当然,这不起作用,因为它已被翻译成

val b = a flatMap (xs => xs map (el => el + 1))

而我正在寻找

val b = a map (xs => xs map (el => el + 1))

为了理解这一点,我必须将它们嵌套:

val b = for {
  xs <- a
} yield for {
  el <- xs
} yield el + 1

这最后一种形式有效。有没有办法使用第一种形式获得相同的结果?我觉得我已经使用Kleisli作曲或monad变形金刚看过这些内容,但似乎无法找到我需要的东西。

1 个答案:

答案 0 :(得分:5)

Scalaz中的ListT monad变换器实际上比第一个版本好一点(或者至少更简洁 - 你只需要担心一个层):

import scalaz._, Scalaz._

val a = ListT(List(1, 2, 3).some)

val b = for { el <- a } yield el + 1

或等效地:

val b = a.map(_ + 1)

此处ab都是ListT[Option, Int]的实例。您可以使用Option[List[Int]]

解包这些值并获得普通的underlying
scala> b.underlying
res0: Option[List[Int]] = Some(List(2, 3, 4))

您可以使用ListT执行许多其他操作,例如从值到列表选项的序列函数等。