2013-10-21 72 views

回答

7

在MonadPlus中有一種方法:separatedefined。此類型類型是Monad與PlusEmpty(廣義Monoid)的組合。所以,你需要爲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) 
} 

序列已經單子,所以pointbind容易,emptyplus是幺操作和Seqfree monoid

2)Bifoldable [\ /]

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)) 

更新

感謝Kenji Yoshida,有is一個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) 
    } 
} 
+0

實際上,有在7.0.3/4的臭蟲'.separate'不可用。 – laurencer

+0

https://github.com/scalaz/scalaz/blob/v7.1.0-M3/core/src/main/scala/scalaz/MonadPlus.scala#L24請使用7.1.0-M3 –

+1

https:// github。 com/scalaz/scalaz/blob/v7.1.0-M3/core/src/main/scala/scalaz/Either.scala#L373有Bifoldable [\ /]。 Bitraverse是Bifoldable的子類型 –

相關問題