Does Cats provide flattening akin to
implicit class FlattenListOfEither[L, R](l: List[Either[L, R]]) {
def flattenM: List[R] = l collect { case Right(v) => v }
}
such that
val l1: List[Either[String, Int]] = List(Right(1), Right(2), Left("error"), Right(4))
l1.flattenM
outputs
List(1, 2, 4)
similar to how vanilla Scala flattens list of options
val l2: List[Option[Int]] = List(Some(1), Some(2), None, Some(4))
l2.flatten
which outputs
List(1, 2, 4)
separate
gives the following syntax
import cats.implicits._
val (_, rights) = l1.separate
rights
which outputs
List(1, 2, 4)
however does there exist out-of-the-box flatten
-like extension method which returns just the rights instead of the tuple?
I think the easiest is to use mapFilter
provided by the FunctorFilter
typeclass.
It looks like this:
def mapFilter[A, B](fa: F[A])(f: (A) ⇒ Option[B]): F[B]
Where F[A]
could be List[A]
, or Vector[A]
or any other type that allows filtering.
If we apply this function to your list, we just need to turn the Either[A, B]
s into Option[B]
s. This is as easy as calling toOption
.
With that the full solution looks like this:
import cats.implicits._
val l1: List[Either[String, Int]] = List(Right(1), Right(2), Left("error"), Right(4))
l1.mapFilter(_.toOption)
// List(1, 2, 4)