Logo Questions Linux Laravel Mysql Ubuntu Git Menu
 

Future[List[Error \/ Double]] to Future[[List[Error] \/ List[Double]] in Scala

I'm playing around with Scala(z) to learn functionnal programming.

I have a value of type Future[List[Error \/ Double]] and want to transform it to something with the type Future[[List[Error] \/ List[Double]].

The goal is to group the lefts and rights.

I currently have the following:

val foo: Future[List[Error] \/ List[Double]] = {
  for {
    results <- resultsF
  } yield
    results.foldLeft(\/[List[Error], List[Double]])({
      case (acc, v) if v.isRight => v :: \/-(acc)
      case (acc, v) if v.isLeft => v :: -\/(acc)
    })
}

However, I get an error on the :: which is due to the fact that my accumulator is not a list (from the outside) \/[List[Error], List[Double]]. How should it be done?

like image 512
DennisVDB Avatar asked Aug 30 '16 12:08

DennisVDB


1 Answers

This function in Haskell would be partitionEithers: [Either a b] -> ([a], [b]).

(You don't actually want Either [a] [b], that wouldn't really make sense. I'm guessing you want this function instead because of the text in your description...)

Scalaz doesn't have it as-is. However, it has a more general separate:

/** Generalized version of Haskell's `partitionEithers` */
def separate[G[_, _], A, B](value: F[G[A, B]])(implicit G: Bifoldable[G]): (F[A], F[B])

Which is basically Bifoldable g, MonadPlus f => f (g a b) -> (f a), (f b). Specifically: [Either a b] -> ([a], [b]). You can simply call it on your list (where g = \/ (or Either), f = List).

In action:

scala> import scalaz._, Scalaz._
scala> List(\/-(3), -\/("a")).separate
res1: (List[String], List[Int]) = (List(a),List(3))
like image 67
Ven Avatar answered Nov 15 '22 13:11

Ven