为什么我不能在此scala模式匹配中解压缩值?

时间:2015-01-18 21:32:50

标签: scala

我试图在scala中使用光滑(使用独角兽)查找用户。这是我的代码:

class UserRepository extends BaseIdRepository[UserId, User, Users](TableQuery[Users]) with IdentityService[User] {

  /**
   * Retrieve the User associated with the given LoginInfo, if any. This method
   * is required by Silhouette.
   * @param loginInfo
   */
  override def retrieve(loginInfo: LoginInfo): Future[Option[User]] = {
    Future.successful {
      val loginInfoRepository = new LoginInfoRepository
      loginInfoRepository.find(loginInfo) match {
        case Some(retrievedLoginInfo) =>
          val userLoginInfoJunctionRepository = new UserLoginInfoJunctionRepository
          // problem here...
          userLoginInfoJunctionRepository.forB(retrievedLoginInfo.id).firstOption
        case None => None
      }
    }
  }
}

class LoginInfoRepository extends BaseIdRepository[DbLoginInfoId, DbLoginInfo, LoginInfos](TableQuery[LoginInfos]) {
  def find(loginInfo: LoginInfo) = query.filter(
    l =>
      l.providerID == loginInfo.providerID &&
      l.providerKey == loginInfo.providerKey
  ).firstOption
}

在上面标记的行上,intellij打印"类型不匹配。预期DbLoginInfoId,实际选项[DbLoginInfoId]"。

我是否在选项中有选项,因此retrievedLoginInfo实际上是Option[retrievedLoginInfo]?如何正确解压缩,以便我可以访问retrievedLoginInfo

的ID

2 个答案:

答案 0 :(得分:2)

idLoginInfo的{​​{1}}类似Option[DbLoginInfoId],但forBDbLoginInfoId

您需要映射retrievedLoginInfo.id以提取实际值。您可以通过更好的理解来重构整个事物,例如:

for {
  retrievedLoginInfo <- loginInfoRepository.find(loginInfo)
  id <- retrievedLoginInfo.id
  userLoginInfoJunctionRepository = new UserLoginInfoJunctionRepository
  res <- userLoginInfoJunctionRepository.forB(id).firstOption
} yield res

答案 1 :(得分:1)

对我来说很好看。我认为这个问题中缺少一些信息吗?

一旦我在这段代码中填充了足够的上下文,它就会编译。此代码中您的部分未经更改:

import scala.concurrent.Future

package object foo {

  trait LoginInfo {
    def providerID: Any
    def providerKey: Any
  }
  abstract class BaseIdRepository[A, B, C](x: Any)
  trait IdentityService[A] {
    def retrieve(loginInfo: LoginInfo): Future[Option[User]]
  }
  trait User {
    def id: UserId
  }
  trait UserId
  trait Users
  def TableQuery[A] = ???
  class UserLoginInfoJunctionRepository {
    def forB(x: UserId): QueryResult[User] = ???
  }
  trait DbLoginInfoId
  trait DbLoginInfo
  trait LoginInfos
  trait QueryResult[A] {
    def firstOption: Option[A] = ???
  }
  class Query {
    def filter(f: LoginInfo => Boolean): QueryResult[User] = ???
  }
  val query = new Query()

  // ----

  class UserRepository extends BaseIdRepository[UserId, User, Users](TableQuery[Users]) with IdentityService[User] {

    /**
     * Retrieve the User associated with the given LoginInfo, if any. This method
     * is required by Silhouette.
     * @param loginInfo
     */
    override def retrieve(loginInfo: LoginInfo): Future[Option[User]] = {
      Future.successful {
        val loginInfoRepository = new LoginInfoRepository
        loginInfoRepository.find(loginInfo) match {
          case Some(retrievedLoginInfo) =>
            val userLoginInfoJunctionRepository = new UserLoginInfoJunctionRepository
            // problem here...
            userLoginInfoJunctionRepository.forB(retrievedLoginInfo.id).firstOption
          case None => None
        }
      }
    }
  }

  class LoginInfoRepository extends BaseIdRepository[DbLoginInfoId, DbLoginInfo, LoginInfos](TableQuery[LoginInfos]) {
    def find(loginInfo: LoginInfo) = query.filter(
      l =>
        l.providerID == loginInfo.providerID &&
          l.providerKey == loginInfo.providerKey
    ).firstOption
  }
}

如果您可以将问题减少到一个最小的例子,那就容易多了。