【问题标题】:Scala applying a PartialFunction with () is not the same as .apply()Scala 使用 () 应用 PartialFunction 与 .apply() 不同
【发布时间】:2015-08-31 10:44:28
【问题描述】:

当我想到这个想法时,我正试图在一个项目(Play Framework 2.4)中重构我的 scala 代码:

(为了提供一个最小的工作示例,我更改了一些类,例如,我分别将 Result 和 Future[Result] 更改为 Int 和 Option[Int])

object ParFuncApply {

  trait CanBeAuthenticatedRequest[A]
  trait AuthenticatedRequest[A] extends CanBeAuthenticatedRequest[A]
  trait UnauthenticatedRequest[A] extends CanBeAuthenticatedRequest[A]


  private def fold[T](authenticated: (AuthenticatedRequest[_]) => T)
                             (unauthenticated: (UnauthenticatedRequest[_]) => T):
  PartialFunction[CanBeAuthenticatedRequest[_], T] = {
    case ar: AuthenticatedRequest[_] => authenticated(ar)
    case ur: UnauthenticatedRequest[_] => unauthenticated(ur)
  }

  def apply(request: CanBeAuthenticatedRequest[_])
           (authenticated: (AuthenticatedRequest[_]) => Int)
           (unauthenticated: (UnauthenticatedRequest[_]) => Int): Int = {
    fold(authenticated)(unauthenticated)(request)
  }

  def async(request: CanBeAuthenticatedRequest[_])
           (authenticated: (AuthenticatedRequest[_]) => Option[Int])
           (unauthenticated: (UnauthenticatedRequest[_]) => Option[Int]): Option[Int] = {
    fold(authenticated)(unauthenticated)(request)
  }
}

上面的代码可以编译。

然后我:我应该将 fold[T] 参数化类型限制为 Int 和 Option[Int],所以我添加了:

object ParFuncApply {

  trait CanBeAuthenticatedRequest[A]
  trait AuthenticatedRequest[A] extends CanBeAuthenticatedRequest[A]
  trait UnauthenticatedRequest[A] extends CanBeAuthenticatedRequest[A]

  sealed trait Helper[T]

  object Helper {
    implicit object FutureResultHelper extends Helper[Option[Int]]
    implicit object ResultHelper extends Helper[Int]
  }

  private def fold[T: Helper](authenticated: (AuthenticatedRequest[_]) => T)
                             (unauthenticated: (UnauthenticatedRequest[_]) => T):
  PartialFunction[CanBeAuthenticatedRequest[_], T] = {
    case ar: AuthenticatedRequest[_] => authenticated(ar)
    case ur: UnauthenticatedRequest[_] => unauthenticated(ur)
  }

  def apply(request: CanBeAuthenticatedRequest[_])
           (authenticated: (AuthenticatedRequest[_]) => Int)
           (unauthenticated: (UnauthenticatedRequest[_]) => Int): Int = {
    fold(authenticated)(unauthenticated)(request)
  }

  def async(request: CanBeAuthenticatedRequest[_])
           (authenticated: (AuthenticatedRequest[_]) => Option[Int])
           (unauthenticated: (UnauthenticatedRequest[_]) => Option[Int]): Option[Int] = {
    fold(authenticated)(unauthenticated)(request)
  }
}

但是,如果我更改,则此代码不再编译: fold(authenticated)(unauthenticated)(request)fold(authenticated)(unauthenticated).apply(request)(我添加了对 apply() 的显式调用)它编译。为什么会这样?在一个类上调用 () 和 .apply() 应该是一样的,不是吗?

编译器似乎要求将返回类型(Int 或 Option[Int])传递给 PartialFunction,而不是 CanBeAuthenticatedRequest 类型。

【问题讨论】:

    标签: scala compiler-errors partialfunction


    【解决方案1】:

    因为您在 `fold[T : Helper]' 中定义了一个上下文绑定,编译器将添加另一个参数列表。换句话说,上下文绑定只是语法糖:

    private def fold[T](authenticated: (AuthenticatedRequest[_]) => T)
                       (unauthenticated: (UnauthenticatedRequest[_]) => T)
                       (implicit helper: Helper[T): PartialFunction[CanBeAuthenticatedRequest[_], T] 
    

    所以当你打电话时

    fold(authenticated)(unauthenticated)(request)
    

    编译器认为request 应该是一个明确指定的隐式Helper[T]。

    【讨论】:

    • @vicaba 另外,不是调用apply,另一个常见的解决方法是在调用它之前先将部分函数分配给一个val。例如。 val f = fold(authenticated)(unauthenticated)f(request)
    猜你喜欢
    • 1970-01-01
    • 1970-01-01
    • 1970-01-01
    • 2012-01-10
    • 1970-01-01
    • 1970-01-01
    • 1970-01-01
    • 1970-01-01
    • 2017-03-20
    相关资源
    最近更新 更多