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
}
}
正如您所看到的,隐式类不起作用。我必须新ActionFilterOps
答案 0 :(得分:3)
作为旁注:如果你有一个不依赖于外部依赖关系(如Play)的自包含示例,那么它会有所帮助。
现在回答问题,或者至少修正错误......如果你将类型别名ActionFilter
更改为包含函数的类,它就可以工作。
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
}
尤其是第二个解决方案"让我觉得这是一个错误。