隐性课程有时无法奏效

时间:2016-12-14 09:50:48

标签: scala implicit-conversion

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

1 个答案:

答案 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
}

尤其是第二个解决方案"让我觉得这是一个错误。