scala - 使用Scalaz将选项列表转换为列表选项

标签 scala option scalaz

我想将List[Option[T]]转换为Option[List[T]]。函数的签名类型为

def lo2ol[T](lo: List[Option[T]]): Option[List[T]]

预期的行为是将仅包含Some的列表映射到包含元素Some内的元素列表的Some。另一方面,如果输入列表中至少有一个None,则预期的行为是仅返回None。例如:
scala> lo2ol(Some(1) :: Some(2) :: Nil)
res10: Option[List[Int]] = Some(List(1, 2))

scala> lo2ol(Some(1) :: None :: Some(2) :: Nil)
res11: Option[List[Int]] = None

scala> lo2ol(Nil : List[Option[Int]])
res12: Option[List[Int]] = Some(List())

没有scalaz的示例实现为:
def lo2ol[T](lo: List[Option[T]]): Option[List[T]] = {
  lo.foldRight[Option[List[T]]](Some(Nil)){(o, ol) => (o, ol) match {
    case (Some(x), Some(xs)) => Some(x :: xs);
    case _ => None : Option[List[T]]; 
}}}

我记得在某个地方看到过类似的示例,但是使用Scalaz简化了代码。看起来如何?

使用Scala2.8 PartialFunction.condOpt的版本更为简洁,但仍然没有Scalaz:
import PartialFunction._

def lo2ol[T](lo: List[Option[T]]): Option[List[T]] = {
  lo.foldRight[Option[List[T]]](Some(Nil)){(o, ol) => condOpt(o, ol) {
    case (Some(x), Some(xs)) => x :: xs
  }
}}

最佳答案

有一个函数可以在Scalaz中将List[Option[A]]转换为Option[List[A]]。这是sequence。要在所有元素均为None的情况下获取None,而在所有元素均为Some[List[A]]的情况下获取Some,则可以执行以下操作:

import scalaz.syntax.traverse._
import scalaz.std.list._     
import scalaz.std.option._

lo.sequence

如果存在F[G[A]G[F[A]]的实现,则此方法实际上将Traverse[F]转换为Applicative[G](OptionList恰好满足了这两个要求,并由这些导入提供)。
Applicative[Option]的语义是,如果ListOption的任何元素都是None,那么sequence也将是None。如果要获取所有Some值的列表,而不管是否有其他值是None,则可以执行以下操作:
lo flatMap (_.toList)

您可以对也形成Monad的任何Monoid进行概括(List恰好是其中之一):
import scalaz.syntax.monad._

def somes[F[_],A](x: F[Option[A]])
                 (implicit m: Monad[F], z: Monoid[F[A]]) =
  x flatMap (o => o.fold(_.pure[F])(z.zero))

关于scala - 使用Scalaz将选项列表转换为列表选项,我们在Stack Overflow上找到一个类似的问题: https://stackoverflow.com/questions/2569014/

相关文章:

scala - 未装箱的标记类型安全吗?

scala - 在 scalaz `Option[Tuple]` 中转换 `\/`

java - sbt 正在使用 "default"项目而不是创建一个新项目

scala - 在 Sbt 中包含 Spark 包

scala - 将 1 个元素的列表转换为选项

javascript - 防止在输入字段中运行JS代码,然后由JS添加

scala - Scalaz 中的 Task 和 IO 有什么区别?

scala - 如何构建客户端直接文件上传到 Play Framework (Scala)

scala - 如何在 Scala 中迭代定义对象中的内部对象

python - 如何在Finder中制作“右键单击选项”? (苹果电脑)