【发布时间】:2021-08-31 14:41:04
【问题描述】:
我想知道 Scala 中的惯用方式是将Option[A] 的Seq 转换为Option[Seq[A]],如果任何输入选项为None,则结果为None。
【问题讨论】:
标签: scala functional-programming optional
我想知道 Scala 中的惯用方式是将Option[A] 的Seq 转换为Option[Seq[A]],如果任何输入选项为None,则结果为None。
【问题讨论】:
标签: scala functional-programming optional
惯用的方式可能是使用通常所说的traverse。
我建议阅读 Cats 的相关文档:https://typelevel.org/cats/typeclasses/traverse.html
有了 Cats,就很简单了:
import cats.implicits
val list = List(Some(1), Some(2), None)
// list: List[Option[Int]] = List(Some(1), Some(2), None)
val traversed = list.traverse(identity)
// traversed: Option[List[Int]] = None
// Or in this specific case:
val sequenced = list.sequence
// sequenced: Option[List[Int]] = None
【讨论】:
标准库提供partitionMap,帮助实现sequence操作
_.partitionMap(_.toRight("")) match {
case (Nil, xs) => Some(xs)
case _ => None
}
这是一个可能的通用实现作为扩展方法
extension [CC[x] <: IterableOps[x, CC, CC[x]], A](xs: CC[Option[A]])
def sequence: Option[CC[A]] =
xs.partitionMap(_.toRight("")) match {
case (lefts, as) if lefts.isEmpty => Some(as)
case _ => None
}
【讨论】:
Nil 会限制可能的集合类型。备选:.pipe(tup => if (tup._1.isEmpty) Some(tup._2) else None)