Given:
def convert[T](list: List[Either[String, T]]): Validated[NonEmptyList[String], NonEmptyList[T]] =
NonEmptyList.fromList(list)
.toRight("list is empty")
.flatMap(...
How do I flat map the NonEmptyList[Either[String, T]]
so ultimately I end up with my Validated
return value?
Is there anything in the cats
library to account for this scenario? Or do I need to do this manually following something like: Best way to turn a Lists of Eithers into an Either of Lists?
I'd write this as follows:
import cats.data.{ NonEmptyList, Validated, ValidatedNel }
import cats.instances.list._, cats.syntax.list._
import cats.syntax.either._
import cats.syntax.option._
import cats.syntax.traverse._
def convert[T](list: List[Either[String, T]]): ValidatedNel[String, NonEmptyList[T]] =
list.traverse(_.toValidatedNel).andThen(_.toNel.toValidNel("list is empty"))
First we flip the whole thing inside out while transforming the Either
s to Validated
s (with traverse
and toValidatedNel
), to get a ValidatedNel[String, List[T]]
, and then we handle the case where the result is empty (with andThen
and toNel
).
The andThen
is probably one of the pieces you're missing—it's essentially flatMap
for Validated
(but without the implications and syntactic sugar baggage that flatMap
brings). If you wanted you could probably pretty easily change my version to do the empty list check first, as in your sketch, but the way I've written it feels a little more natural to me.
Footnote: I have no idea why the enrichment method for Option
is named toValidNel
while the one for Either
is toValidatedNel
—I hadn't noticed this before, probably because I hadn't used them in the same line before. This seems unfortunate, especially since we're stuck with it for a while now that Cats 1.0 is out.
Another footnote: note that you'll need the -Ypartial-unification
compiler option enabled for traverse
to work without type parameters if you're on 2.11.
If you love us? You can donate to us via Paypal or buy me a coffee so we can maintain and grow! Thank you!
Donate Us With