Raf*_*ira 28 scala option scalaz
我想把a List[Option[T]]变成a Option[List[T]].函数的签名类型是
def lo2ol[T](lo: List[Option[T]]): Option[List[T]]
Run Code Online (Sandbox Code Playgroud)
预期的行为是将仅包含Somes 的列表映射到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())
Run Code Online (Sandbox Code Playgroud)
没有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]];
}}}
Run Code Online (Sandbox Code Playgroud)
我记得在某个地方看过类似的例子,但是使用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
}
}}
Run Code Online (Sandbox Code Playgroud)
Apo*_*isp 21
有一个函数可以将List[Option[A]]变成Option[List[A]]Scalaz中的函数.是的sequence.为了得到None任何元素,None以及Some[List[A]]所有元素都是Some,你可以这样做:
import scalaz.syntax.traverse._
import scalaz.std.list._
import scalaz.std.option._
lo.sequence
Run Code Online (Sandbox Code Playgroud)
这种方法实际上变成F[G[A]了G[F[A]]存在的实现Traverse[F],并且Applicative[G](Option并且List碰巧满足这两种并且由这些导入提供).
的语义Applicative[Option]是这样的,如果任何一种元素List的Options为None,那么sequence将是None为好.如果要获取所有Some值的列表而不管其他值是否为None,则可以执行以下操作:
lo flatMap (_.toList)
Run Code Online (Sandbox Code Playgroud)
你可以概括为任何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))
Run Code Online (Sandbox Code Playgroud)
Rex*_*err 18
出于某种原因你不喜欢
if (lo.exists(_ isEmpty)) None else Some(lo.map(_.get))
Run Code Online (Sandbox Code Playgroud)
?这可能是没有Scalaz的Scala中最短的.