2016-12-14 5 views
2

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

ответ

3

В качестве примечания: это помогает, если у вас есть самодостаточный пример, который не зависит от внешних зависимостей (например, воспроизведения), если это возможно.

Теперь ответьте или, по крайней мере, исправьте ошибку ... Если вы измените псевдоним типа 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 
} 

Особенно, что второе «решение» заставляет меня думать, что это ошибка.