Scala 使用 () 应用 PartialFunction 与 .apply() 不同
Scala applying a PartialFunction with () is not the same as .apply()
当我想到这个想法时,我正试图在项目 (Play Framework 2.4) 中重构我的 Scala 代码:
(为了提供一个最小的工作示例,我更改了一些 classes,例如,我分别将 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() 的显式调用)它编译。为什么会这样?在 class 上调用 () 和 .apply() 应该是一样的,不是吗?
编译器似乎要求将 return 类型(Int 或 Option[Int])传递给 PartialFunction 而不是 CanBeAuthenticatedRequest 类型。
因为您在`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]。
当我想到这个想法时,我正试图在项目 (Play Framework 2.4) 中重构我的 Scala 代码:
(为了提供一个最小的工作示例,我更改了一些 classes,例如,我分别将 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() 的显式调用)它编译。为什么会这样?在 class 上调用 () 和 .apply() 应该是一样的,不是吗?
编译器似乎要求将 return 类型(Int 或 Option[Int])传递给 PartialFunction 而不是 CanBeAuthenticatedRequest 类型。
因为您在`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]。