我正在尝试实现如下所示,其中 a
和 b
都属于 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 转换器看到了类似的东西,但似乎找不到我需要的东西。
最佳答案
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)
这里的a
和b
都是ListT[Option, Int]
的实例。您可以使用 underlying
展开这些值并获得普通的旧 Option[List[Int]]
:
scala> b.underlying
res0: Option[List[Int]] = Some(List(2, 3, 4))
您可以使用 ListT
做很多其他事情,例如从值到列表选项的序列函数等。
关于scala - 避免嵌套理解与 monadic 操作,我们在Stack Overflow上找到一个类似的问题: https://stackoverflow.com/questions/22366468/