Future[Option] in Scala for-comprehensions -
i have 2 functions return futures. i'm trying feed modified result first function other using for-yield comprehension.
this approach works:
val schoolfuture = { ud <- userstore.getuserdetails(user.userid) sid = ud.right.tooption.flatmap(_.schoolid) s <- schoolstore.getschool(sid.get) if sid.isdefined } yield s
however i'm not happy having "if" in there, seems should able use map instead.
but when try map:
val schoolfuture: future[option[school]] = { ud <- userstore.getuserdetails(user.userid) sid = ud.right.tooption.flatmap(_.schoolid) s <- sid.map(schoolstore.getschool(_)) } yield s
i compile error:
[error] found : option[scala.concurrent.future[option[school]]] [error] required: scala.concurrent.future[option[school]] [error] s <- sid.map(schoolstore.getschool(_))
i've played around few variations, haven't found attractive works. can suggest nicer comprehension and/or explain what's wrong 2nd example?
here minimal complete runnable example scala 2.10:
import concurrent.{future, promise} case class user(userid: int) case class userdetails(userid: int, schoolid: option[int]) case class school(schoolid: int, name: string) trait error class userstore { def getuserdetails(userid: int): future[either[error, userdetails]] = promise.successful(right(userdetails(1, some(1)))).future } class schoolstore { def getschool(schoolid: int): future[option[school]] = promise.successful(option(school(1, "big school"))).future } object demo { import concurrent.executioncontext.implicits.global val userstore = new userstore val schoolstore = new schoolstore val user = user(1) val schoolfuture: future[option[school]] = { ud <- userstore.getuserdetails(user.userid) sid = ud.right.tooption.flatmap(_.schoolid) s <- sid.map(schoolstore.getschool(_)) } yield s }
this answer similar question promise[option[a]]
might help. substitute future
promise
.
i'm inferring following types getuserdetails
, getschool
question:
getuserdetails: userid => future[either[??, userdetails]] getschool: schoolid => future[option[school]]
since ignore failure value either
, transforming option
instead, have 2 values of type a => future[option[b]]
.
once you've got monad
instance future
(there may 1 in scalaz, or write own in answer linked), applying optiont
transformer problem this:
for { ud <- optiont(getuserdetails(user.userid) map (_.right.tooption)) sid <- optiont(future.successful(ud.schoolid)) s <- optiont(getschool(sid)) } yield s
note that, keep types compatible, ud.schoolid
wrapped in (already completed) future.
the result of for-comprehension have type optiont[future, schoolid]
. can extract value of type future[option[schoolid]]
transformer's run
method.
Comments
Post a Comment