Scala Task return mapping

342 Views Asked by At

I have a method readHeader which takes one argument and returns Task[List[Header]] and another method calls for multiple ids and returns List[Task[List[EquipmentHeader]]]. How to make a return of Task[List[List[Header]]] compatible with multiple id read function.

trait M1{
  def readHeader(id: String): Task[List[Header]]
}

def read(ids: List[String])(implicit m1:M1):Task[List[List[Header]]] = {
    if (ids.isEmpty) {
      Task(List.empty)
    } else {
         ids.map(m1.readHeader(_)) //List[Task[List[Header]]]
    }
  }
2

There are 2 best solutions below

1
On BEST ANSWER

You can use traverse from cats:

import cats.implicits._

ids.traverse(m1.readHeader) // Task[List[List[Header]]]
0
On

Here is a naive implementation of traverse for just Task and List.
But again, I insist, there is no reason for not using the one defined in cats.

def traverse[A, B](list: List[A])(f: A => Task[B]): Task[List[B]] = {
  @annotation.tailrec
  def loop(remaining: List[A], acc: Task[List[B]]): Task[List[B]] =
    remaining match {
      case a :: as =>
        loop(
          remaining = as,
          acc = for {
            b <- f(a)
            bs <- acc
          } yield b :: bs
        )

      case Nil =>
        acc.map(_.reverse)
    }
  loop(remaining = list, acc = Task.pure(List.empty))
}