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

Popular posts from this blog

php - failed to open stream: HTTP request failed! HTTP/1.0 400 Bad Request -

java - How to filter a backspace keyboard input -

java - Show Soft Keyboard when EditText Appears -