scala - 避免嵌套理解与 monadic 操作

标签 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 转换器看到了类似的东西,但似乎找不到我需要的东西。

最佳答案

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]的实例。您可以使用 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/

相关文章:

scala - 为什么spark broadcast在我用extends App的时候效果不好?

Scala:展平混合集合(或列表或数组)

scala - 一种情况下的多个给定

haskell - 将两个(或多个)选项值应用于 F# 中的函数的正确方法

scala - 为什么以下 scala 实验代码不起作用?

scala - 旋转 View 引擎外观相似

clojure - 什么时候使用 Clojure 的闭包?

scala - | + |是一个半群,为什么它需要一个monoid隐式解析

scala - NonEmptyList 的 Monad 转换器?

scala - 使用哪个 Monad Transformer?