我正在寻找一个更通用的解决方案,利用monad(和可能的monoid)来实现相同的
if( xs.contains(None) ) None else Some(xs.flatten)
为...做 xs
类型 Seq[Option[A]]
。
我怎么能用Scalaz做到这一点?我觉得我错过了一些明显的东西。
我正在寻找一个更通用的解决方案,利用monad(和可能的monoid)来实现相同的
if( xs.contains(None) ) None else Some(xs.flatten)
为...做 xs
类型 Seq[Option[A]]
。
我怎么能用Scalaz做到这一点?我觉得我错过了一些明显的东西。
有两个monad是不够的(为 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))
无需额外打字。
有两个monad是不够的(为 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))
无需额外打字。