拥有两个单子是不够的(对于M
)并且绰绰有余(对于N
)——当然,这加起来还不够——但是如果M
has a Traverse
实例和N
has an Applicative
实例,你可以使用sequence
。例如:
import scalaz._, Scalaz._
def foo[A](xs: List[Option[A]]): Option[List[A]] = xs.sequence
这有你想要的语义。请注意,我正在使用List
代替Seq
,因为 Scalaz 7 不再提供必要的Traverse
实例为Seq
(尽管你可以轻松地编写自己的)。
正如您所注意到的,以下内容将无法编译:
List(Some(1), Some(45)).sequence
虽然如果你扔一个也没关系None
在那里:
scala> List(Some(1), None, Some(45)).sequence
res0: Option[List[Int]] = None
这是因为推断的类型List(Some(1), Some(45))
将List[Some[Int]]
,并且我们没有Applicative
实例为Some
.
Scalaz 提供了一个方便的some
方法的工作原理如下Some.apply
但给你一些已经输入的内容Option
,因此您可以编写以下内容:
scala> List(some(1), some(45)).sequence
res1: Option[List[Int]] = Some(List(1, 45))
无需额外打字。