I would like to know how to convert a List[Try[T]]
into Try[List[T]]
in Scala?
I have tried using an accumulator and folding right but it do
Using cats it's as easy as:
import cats._
import cats.data._
import cats.implicits._
import scala.util.{Try, Success, Failure}
val tries: List[Try[Int]] = List(Success(1), Success(2), Success(3))
tries.sequence
More information in the Traverse docs.
Try(list.map(_.get))
This will return only the first failure, so you need something more complicated if you want to catch all the failures in the list.
I would also recommend just using Cats...
But, if you do not want to add another (big) dependency to your project, just for one function.
You can implement it your self! - (cats implementation may be better)
import scala.util.{Try, Success, Failure}
def sequence[A](list: List[Try[A]]): Try[List[A]] = {
@annotation.tailrec
def loop(remaining: List[Try[A]], acc: List[A]): Try[List[A]] =
remaining match {
case Nil => Success(acc.reverse)
case Success(a) :: tail => loop(remaining = tail, acc = a :: acc)
case Failure(e) :: _ => Failure(e)
}
loop(remaining = list, acc = List.empty)
}
Also, if you may use traverse
instead of sequence
if you did a map
just before.
def traverse[A, B](list: List[A])(f: A => Try[B]): Try[List[B]] = {
@annotation.tailrec
def loop(remaining: List[A], acc: List[B]): Try[List[B]] =
remaining match {
case Nil => Success(acc.reverse)
case head :: tail => f(head) match {
case Success(b) => loop(remaining = tail, acc = b :: acc)
case Failure(e) => Failure(e)
}
}
loop(remaining = list, acc = List.empty)
}
Anyways, Cats (and FP in general) is very useful (as you have just seen).
Thus, I would recommend you to give it a try.
Cats is a nice way to go but it can be done via the Standard Library without too much complication.
import util.{Try, Success, Failure}
def seqnc[T](lst :List[Try[T]]) :Try[List[T]] =
lst.foldRight(Try(List.empty[T])) {
case (tt, acc) => for { t <- tt
a <- acc
} yield t :: a
}