Scalaz中析取序列的划分

Scalaz中析取序列的划分,scala,functional-programming,scalaz,Scala,Functional Programming,Scalaz,使用Scalaz将Seq[A\/B]划分为(Seq[A],Seq[B])的最佳方法是什么?在MonadPlus中有一种方法:separate。这个类型类是一个单子与复数(广义幺半群)的组合。因此,您需要为Seq定义实例: 1) MonadPlus[序列] implicit val seqmp = new MonadPlus[Seq] { def plus[A](a: Seq[A], b: => Seq[A]): Seq[A] = a ++ b def empty[A]: Seq[A

使用Scalaz将
Seq[A\/B]
划分为
(Seq[A],Seq[B])
的最佳方法是什么?

在MonadPlus中有一种方法:
separate
。这个类型类是一个单子与复数(广义幺半群)的组合。因此,您需要为
Seq
定义实例:

1) MonadPlus[序列]

implicit val seqmp = new MonadPlus[Seq] {
  def plus[A](a: Seq[A], b: => Seq[A]): Seq[A] = a ++ b
  def empty[A]: Seq[A] = Seq.empty[A]
  def point[A](a: => A): Seq[A] = Seq(a)
  def bind[A, B](fa: Seq[A])(f: (A) => Seq[B]): Seq[B] = fa.flatMap(f)
}
Seq已经是一元的,所以
绑定
很容易,
是幺半群运算,
Seq
是一个

2) 双折叠的[\/]

implicit val bife = new Bifoldable[\/] {
    def bifoldMap[A, B, M](fa: \/[A, B])(f: (A) => M)(g: (B) => M)(implicit F: Monoid[M]): M = fa match {
      case \/-(r) => g(r)
      case -\/(l) => f(l)
    }

    def bifoldRight[A, B, C](fa: \/[A, B], z: => C)(f: (A, => C) => C)(g: (B, => C) => C): C = fa match {
      case \/-(r) => g(r, z)
      case -\/(l) => f(l, z)
    }
  }
也很容易,标准折叠,但是对于具有两个参数的类型构造函数

现在,您可以使用单独的:

val seq: Seq[String \/ Int] = List(\/-(10), -\/("wrong"), \/-(22), \/-(1), -\/("exception"))
scala> seq.separate
res2: (Seq[String], Seq[Int]) = (List(wrong, number exception),List(10, 22, 1))
更新

多亏了,这里有一个Bitraverse[\/],所以您只需要MonadPlus

以及使用
foldLeft
的简单解决方案:

seq.foldLeft((Seq.empty[String], Seq.empty[Int])){ case ((as, ai), either) =>
  either match {
    case \/-(r) => (as, ai :+ r)
    case -\/(l) => (as :+ l, ai)
  }
}

实际上7.0.3/4中有一个bug,
.separate
不可用。请使用7.1.0-M3,有双折[\/]。Bitraverse是双折叠的子类型