我正在寻找一个更通用的解决方案,利用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))
无需额外打字。