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