List[Try[T]] to Try[List[T]] in Scala

前端 未结 4 1073
天涯浪人
天涯浪人 2021-01-20 22:04

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

相关标签:
4条回答
  • 2021-01-20 22:06

    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.

    0 讨论(0)
  • 2021-01-20 22:06
    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.

    0 讨论(0)
  • 2021-01-20 22:10

    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.

    0 讨论(0)
  • 2021-01-20 22:14

    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
      }
    
    0 讨论(0)
提交回复
热议问题