Reputation: 47
I have a hashmap map: Map[A, Seq[B]]
and I want to call a future function (that returns Future[Either[Error, Unit]]
) for each B
in my map.
For example, given the following function def fooFunc(hashMap: Map[A, Seq[B]]): Future[Either[Error, Unit]]
I tried something like
def fooFunc(hashMap: Map[A, Seq[B]]): Future[Either[Error, Unit]] = {
val result = for {
_ <- hashMap.map(entry =>
entry._2.map( value =>
Future.sequence(futureFunc(value, entry._1)).liftF
)
)
} yield ()
result.value
}
which gives the compile error Type mismatch, expected: NotInferedM[Future[NotInferedA]], actual: [Future[Either[Error, Unit]]]
This is my first time dealing with futures and iterating over hashmap, so I'm confused how to exactly go about this and deal with the Iterable. Any tips would be appreciated
Upvotes: 0
Views: 267
Reputation: 48430
We can map over a HashMap
just like any other collection such as List
m.flatMap({ case (key, values) => values.map(f(_, key)) })
where m: Map[A, Seq[B]]
and f: (B, A) => Future[Unit]
. This returns Iterable[Future[Unit]]
so we can use Future.sequence
to invert to Future[Iterable[Unit]]
m
.flatMap({ case (key, values) => values.map(f(_, key)) })
.pipe(Future.sequence(_))
Futures internally represent success/failure using Try
which we can convert to Either
using transform
and toEither
like so
m // : Map[A, Seq[B]]
.flatMap({ case (key, values) => values.map(f(_, key)) }) // : Iterable[Future[Unit]]
.pipe(Future.sequence(_)) // : Future[Iterable[Unit]]
.map(_ => ()) // : Future[Unit]
.transform(tryResult => Success(tryResult.toEither)) // : Future[Either[Throwable, Unit]]
which returns the required Future[Either[Error, Unit]]
type. The pipe
method comes from import util.chaining._
Personally, the transformation from Map[A, Seq[B]]
to Future[Either[Error, Unit]]
, feels a bit suspect.
Upvotes: 1