I would like to have a function that converts any iterable type C[_]
of Either[A, B]
to Either[C[A], C[B]]
.
I got it working but I used asInstanceOf
method and I feel like this approach can fail in some scenario (I don't yet know what scenerio that would be since I don't quite understand CanBuildFrom
resolving).
I think that I should implement it using custom CanBuildFrom
but I hope there is easier way of doing that.
Here's my approach:
type IterableCollection[A[_], B] = A[B] with Iterable[B]
implicit class IterableEither[C[_], A, B](self: IterableCollection[C, Either[A, B]]) {
def accumulate: Either[IterableCollection[C, A], IterableCollection[C, B]] = {
val failures = self.collect { case x @ Left(_) => x.value }.asInstanceOf[IterableCollection[C, A]]
if (failures.nonEmpty) Left(failures)
else Right(self.collect { case x @ Right(_) => x.value }.asInstanceOf[IterableCollection[C, B]])
}
}
I've been programming in Scala for a while but have never relied on asInstanceOf
and thus I am a bit afraid of introducing this kind of code to a production environment. Do you guys see a way of doing this without a cast?
With cats it would be a function that traverses eithers through Validated and back to Either. The reason to convert to Validated is that sequence requires Applicative instance.
import cats.Traverse
import cats.data.{NonEmptyList, ValidatedNel}
import cats.implicits._
def accSequence[T[_], A, B](tab: T[Either[A, B]])(implicit T: Traverse[T]): Either[NonEmptyList[A], T[B]] =
tab.traverse[ValidatedNel[A, ?], B](_.toValidatedNel).toEither
val result: Either[NonEmptyList[Int], List[String]] = accSequence(List(Left(1), Right("A"), Left(2)))
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