12

我正在寻找一种更通用的解决方案,它利用 monads(可能还有 monoids)来实现与 if( xs.contains(None) ) None else Some(xs.flatten)for xsof type相同的效果Seq[Option[A]]

我怎么能用 Scalaz 做到这一点?我觉得我错过了一些明显的东西。

4

1 回答 1

14

有两个 monad 是不够的 (for M) 和绰绰有余的 (for N)——当然,这加起来还不够——但是如果M有一个Traverse实例并且N有一个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))

无需额外输入。

于 2012-09-10T20:25:17.910 回答