Scala convert Future[Option[Account]] to Future[Either[String, Option[Account]]] [on hold]

867 views
Skip to first unread message

Владимир Морозов

unread,
May 31, 2014, 4:00:08 AM5/31/14
to scala...@googlegroups.com

I try write code like something this, but I have no idea how to complete that task

db.find(uuid, accountName): Future[Option[Account]]

db.add(uuid, account): Future[Option[Account]]

def add(uuid: UUID, account: Account): Future[Either[String, Option[Account]]] =
    db.find(userId, account.name).map {
        case None =>    
            db.add(userId.uuid, account).map(Right(_))
        case Some(existAccount) =>
            Left(s"Account already exist $existAccount")
    }

Edit: This code can`t compile with error:

Error:(77, 41) type mismatch;
 found   : scala.concurrent.Future[scala.util.Right[Nothing,Option[Account]]]
 required: Either[String,Option[Account]]
        db.add(userId, account).map(Right(_))
                                        ^

Peter Salanki

unread,
May 31, 2014, 4:09:41 AM5/31/14
to Владимир Морозов, scala...@googlegroups.com
Changing the .map to .flatMap and then the left to Future.successful(Left...) should do the trick. You might have to nail down the types for the Right to be interpreted as an Either if the type inferencer can't figure that out.

--
You received this message because you are subscribed to the Google Groups "scala-user" group.
To unsubscribe from this group and stop receiving emails from it, send an email to scala-user+...@googlegroups.com.
For more options, visit https://groups.google.com/d/optout.

Владимир Морозов

unread,
May 31, 2014, 4:42:38 AM5/31/14
to scala...@googlegroups.com, green...@gmail.com, pe...@salanki.st
I try change code to:
def add(uuid: UUID, account: Account): Future[Either[String, Option[Account]]] =
    db.find(userId, account.name).map {
        case None =>
    
            db.add(userId.uuid, account).flatMap { account: Option[Account] =>
          Future.successful(Right[String, Option[Account]](account)) 
        case Some(existAccount) =>
            Future.successful(Left[String, Option[Account]](s"Account already exist $existAccount")
    }

But it create new error:

Error:(77, 46) type mismatch;
 found   : scala.concurrent.Future[scala.util.Right[String,Option[Account]]]
 required: Either[String,Option[Account]]
        db.add(userId, account).flatMap { account: Option[Account] =>
                                             ^
And it not work with both .map and .flatMap

суббота, 31 мая 2014 г., 12:09:41 UTC+4 пользователь Peter Salanki написал:

Som Snytt

unread,
May 31, 2014, 6:42:19 AM5/31/14
to Владимир Морозов, scala-user, pe...@salanki.st
The advice was:

object Test extends App {
  import concurrent._
  import ExecutionContext.Implicits._
  import duration.Duration._
  type Account = String
  val found = """(.+)\1""".r
  def find(name: String) = name match {
    case found(_*) => Future(Option(name))
    case _         => Future(None)
  }
  def add(account: Account) = Future(Option(account * 2))

  def f(account: Account): Future[Either[String, Option[Account]]] = {
    find(account) flatMap {
      case None => add(account) map (Right(_))
      case Some(x) => Future successful Left(s"already $account")
    }
  }
  Console println Await.result(f("bob"), Inf)
  Console println Await.result(f("bobbob"), Inf)
}

$ scalac dbadd.scala && scala dbadd.Test
Right(Some(bobbob))
Left(already bobbob)


Владимир Морозов

unread,
May 31, 2014, 8:39:30 AM5/31/14
to scala...@googlegroups.com, green...@gmail.com, pe...@salanki.st
Awesome!!! You save my day! thank you so much

суббота, 31 мая 2014 г., 14:42:19 UTC+4 пользователь som-snytt написал:
Reply all
Reply to author
Forward
0 new messages