Let's say that I have the following case classes:
case class Record(a: String, b: String)
case class Result(c: Int, d: Int)
And a function that does a bunch of things and then returns an IO[Result]
def processRecord[record: Record]: IO[Result] = {
...
// Returns an IO[Result]
}
I need a function called save
that receives a list of Records
and then needs to combine all the results in one single result
def combineStorageResults(result1: Result, result2: Result) = {
Result(result1.c + result2.c, result1.d/2 + result2.d/2)
}
I've created the following code that does this by using a foldLeft
function. However, as you can see, I need to call unsafeRunSync
in the middle of the process, just to wrap up the result in an IO
at the end... I'm wondering if there is any way to do the same but without having to call unsafeRunSync
in the middle of the function:
def save(records: Seq[Record]): Future[Result] = {
IO(records.foldLeft(Result(0, 0))((previousResult, evt) => {
val processedResult = processRecord(evt).unsafeRunSync()
combineStorageResults(previousResult, processedResult)
}
)).unsafeToFuture()
}
Any help would be greatly appreciated.
You could call processRecord
on each record first, and then combine them. Also use traverse
from cats (works on List, so convert Seq to List)
import cats.effect.IO
import cats.syntax.all._
val processed: IO[List[Result]] = records.toList.traverse(processRecord)
val combined: IO[Result] = processed.map { l =>
l.foldLeft(Result(0, 0))((previousResult, currentResult) => {
combineStorageResults(previousResult, currentResult)
})
}
combined.unsafeToFuture()