为了理解而Futures的类型不匹配

时间:2016-07-13 03:27:18

标签: scala playframework future

我遇到类型不匹配错误,我似乎无法弄清楚原因。

found:        scala.concurrent.Future[UserSales]
required:     Option[UserSales]

       userSalesOpt <- getOrSetUserSales(userSalesCacheKey)

I have tried creating another for {} clause but that didn't solve the issue.  What should I be doing as I am stuck??

以下是我使用的方法:

UserDAO
  def getByUsername(name: String): Future[Option[User]]

UserController: 
  def getOrSetUserSales(key: String): Future[Option[UserSales]]

class UserController ... {

  def index = Action.asyc {
    val maybeUserSalesOpt: Future[Option[UserSales]] = for {
      userOpt <- userDao.getByUsername(name)
    } yield {
       for {
          user <- userOpt
          userSalesCacheKey = name + "whatever"
          userSalesOpt <- getOrSetUserSales(userSalesCacheKey)
       } yield {
         for {
           userSales <- userSalesOpt
         } yield userSales
       }
    }

    for {
      maybeUserSales <- maybeUserSalesOpt
    } yield {
      if(maybeUserSales.isDefined) {
        Ok("found")
      } else {
       Ok("error")
      }

    }

  }

}

1 个答案:

答案 0 :(得分:1)

类型不匹配来自for-comprehension的定义。结果类型必须与声明类型相同。

因此,如果您对List有一个for-comprehension,那么您知道结果类型也是List。

for(i <- List(Some(1), None, Some(2)); j <- i ) yield j
res: List[Int] = List(1, 2)

如果我尝试返回不同的东西,编译器会抱怨:

import scala.concurrent.Future
import scala.concurrent.ExecutionContext.Implicits.global

for(i <- Future.apply(Option(2)); j <- i ) yield j
<console>:**: error: type mismatch;
 found   : Option[Int]
 required: scala.concurrent.Future[?]
              for(i <- Future.apply(Option(2)); j <- i ) yield j
                                                   ^

您正在尝试返回选项,而返回类型应为Future。

以下是如何在Scala中解决这类问题(我抽象所有内容以便编译):

// Dummy types
type UserSales = String
type User = String

// Types of the main functions we have
type GetByUsername = String => Future[Option[User]]
type GetOrSetUserSales = String => Future[Option[UserSales]]

// Type of the function I want
type UserSaleGetter = (String, String) => Future[Option[UserSales]]

// A function that solves our problem (function combinator) 
def makeConditionalUserSalesGetter(userGetter: GetByUsername, 
                                   salesGetter: GetOrSetUserSales): UserSaleGetter = { 
   (userName: String, prodName: String) => 
      for(optUser <- userGetter(userName); p <- salesGetter(userName+prodName) )
          yield p
}

现在我们可以使用组合函数(类型为UserSaleGetter)来为用户和产品提供并返回Future[Option[UserSales]]