隐式 class 有时无法工作
Implicit class sometimes cannot work
Scala 版本:2.11.8
import scala.concurrent.Future
import scala.concurrent.ExecutionContext.Implicits.global
import play.api.mvc._
object foooo {
type ActionFilter[R] = R => Future[Either[Int, Unit]]
case class FooRequest[A](request: Request[A]) extends WrappedRequest(request)
implicit class ActionFilterOps[R](val f: ActionFilter[R]) {
def * (f1: ActionFilter[R]): ActionFilter[R] = { (r: R) =>
f(r).flatMap {
case Left(r) => Future.successful(Left(r))
case Right(_) => f1(r)
}
}
}
def test[A]() = {
val f0: ActionFilter[FooRequest[A]] = { (r: FooRequest[A]) =>
Future.successful(Left(1))
}
val f1 = f0
ActionFilterOps(f1) * f0 // Ok
f1 * f0 // Won't compile
}
}
如您所见,隐式 class 不起作用。我必须更新 ActionFilterOps
附带说明:如果可能的话,如果您有一个不依赖于外部依赖项(例如 Play)的自包含示例,它会有所帮助。
现在开始回答,或者至少修复错误...如果您将类型别名 ActionFilter
更改为包装函数的 class,它就可以工作。
import scala.concurrent.Future
import scala.concurrent.ExecutionContext.Implicits.global
case class ActionFilter[R](f: R => Future[Either[Int, Unit]]) { def apply(r: R) = f(r) }
type Request[A] = Option[A]
case class FooRequest[A](request: Request[A])
implicit class ActionFilterOps[R](val f: ActionFilter[R]) {
def * (f1: ActionFilter[R]): ActionFilter[R] = ActionFilter{ (r: R) =>
f(r).flatMap {
case Left(r) => Future.successful(Left(r))
case Right(_) => f1(r)
}
}
}
def test[A]() = {
val f0: ActionFilter[FooRequest[A]] = ActionFilter{ (r: FooRequest[A]) =>
Future.successful(Left(1))
}
val f1 = f0
ActionFilterOps(f1) * f0 // Ok
f1 * f0 // Ok
}
如果您使用原始函数类型而不是类型别名,它也有效。
import scala.concurrent.Future
import scala.concurrent.ExecutionContext.Implicits.global
type Request[A] = Option[A]
case class FooRequest[A](request: Request[A])
implicit class ActionFilterOps[R](val f: R => Future[Either[Int, Unit]]) {
def * (f1: R => Future[Either[Int, Unit]]): R => Future[Either[Int, Unit]] = { (r: R) =>
f(r).flatMap {
case Left(r) => Future.successful(Left(r))
case Right(_) => f1(r)
}
}
}
def test[A]() = {
val f0: FooRequest[A] => Future[Either[Int, Unit]] = { (r: FooRequest[A]) =>
Future.successful(Left(1))
}
val f1 = f0
ActionFilterOps(f1) * f0 // Ok
f1 * f0 // Ok
}
特别是第二个 "solution" 让我觉得这是一个错误。
Scala 版本:2.11.8
import scala.concurrent.Future
import scala.concurrent.ExecutionContext.Implicits.global
import play.api.mvc._
object foooo {
type ActionFilter[R] = R => Future[Either[Int, Unit]]
case class FooRequest[A](request: Request[A]) extends WrappedRequest(request)
implicit class ActionFilterOps[R](val f: ActionFilter[R]) {
def * (f1: ActionFilter[R]): ActionFilter[R] = { (r: R) =>
f(r).flatMap {
case Left(r) => Future.successful(Left(r))
case Right(_) => f1(r)
}
}
}
def test[A]() = {
val f0: ActionFilter[FooRequest[A]] = { (r: FooRequest[A]) =>
Future.successful(Left(1))
}
val f1 = f0
ActionFilterOps(f1) * f0 // Ok
f1 * f0 // Won't compile
}
}
如您所见,隐式 class 不起作用。我必须更新 ActionFilterOps
附带说明:如果可能的话,如果您有一个不依赖于外部依赖项(例如 Play)的自包含示例,它会有所帮助。
现在开始回答,或者至少修复错误...如果您将类型别名 ActionFilter
更改为包装函数的 class,它就可以工作。
import scala.concurrent.Future
import scala.concurrent.ExecutionContext.Implicits.global
case class ActionFilter[R](f: R => Future[Either[Int, Unit]]) { def apply(r: R) = f(r) }
type Request[A] = Option[A]
case class FooRequest[A](request: Request[A])
implicit class ActionFilterOps[R](val f: ActionFilter[R]) {
def * (f1: ActionFilter[R]): ActionFilter[R] = ActionFilter{ (r: R) =>
f(r).flatMap {
case Left(r) => Future.successful(Left(r))
case Right(_) => f1(r)
}
}
}
def test[A]() = {
val f0: ActionFilter[FooRequest[A]] = ActionFilter{ (r: FooRequest[A]) =>
Future.successful(Left(1))
}
val f1 = f0
ActionFilterOps(f1) * f0 // Ok
f1 * f0 // Ok
}
如果您使用原始函数类型而不是类型别名,它也有效。
import scala.concurrent.Future
import scala.concurrent.ExecutionContext.Implicits.global
type Request[A] = Option[A]
case class FooRequest[A](request: Request[A])
implicit class ActionFilterOps[R](val f: R => Future[Either[Int, Unit]]) {
def * (f1: R => Future[Either[Int, Unit]]): R => Future[Either[Int, Unit]] = { (r: R) =>
f(r).flatMap {
case Left(r) => Future.successful(Left(r))
case Right(_) => f1(r)
}
}
}
def test[A]() = {
val f0: FooRequest[A] => Future[Either[Int, Unit]] = { (r: FooRequest[A]) =>
Future.successful(Left(1))
}
val f1 = f0
ActionFilterOps(f1) * f0 // Ok
f1 * f0 // Ok
}
特别是第二个 "solution" 让我觉得这是一个错误。