问题
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]]]
}
}
回答1:
You can use traverse from cats:
import cats.implicits._
ids.traverse(m1.readHeader) // Task[List[List[Header]]]
回答2:
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))
}
来源:https://stackoverflow.com/questions/59397143/scala-task-return-mapping