6

我有以下方法

def show[E: Writes, T: Writes](block: RequestWithUser[AnyContent] => Either[E, T]): Action[AnyContent] = {
  withErr(block)
}

我从控制器中这样使用:

def show(id: Long) = CrudAuthAction.show { request =>
  IdeaType.findByIdWithErr(id)
}

而且我希望请求方法是可选的,所以我为同一方法定义了另一个签名:

def show[E: Writes, T: Writes](block: => Either[E, T]): Action[AnyContent] = {
  withErr(request => block)
}

它工作正常,我可以省略请求参数

但是当我尝试用另一种方法做同样的事情时

def list[T: Writes](block: RequestWithUser[AnyContent] => T): Action[AnyContent] = {
  fromRequest(block)
}

def list[T: Writes](block: => T): Action[AnyContent] = {
  fromRequest(request => block)
}

当我想这样使用它时:

def list = CrudAuthAction.list { request =>
  IdeaType.find(request.queryString)
}

它告诉我请求缺少参数类型,我必须像这样指定它:

def list = CrudAuthAction.list { request: RequestWithUser[AnyContent] =>

我看不出与第一种情况有什么不同,但 scala 似乎无法推断出正确的请求类型......

我看到的唯一区别是,在第一种情况下,该块返回一个 Either[E,T],但在第二种情况下,它只返回一个通用 T...

4

1 回答 1

5

The problem is that in the second example the compiler does not know which of the overloaded methods to pick, because T could well be a function type. Since Either is clearly not a function, it works in the first case.

To work around this issue, you could change the second method to

def list[T: Writes](block: => Foo[T]): Action[AnyContent] = {
  fromRequest(request => block.v)
}

With Foo defined like that:

case class Foo[T](val v:T)

Unfortunately, adding an implicit conversion to Foo breaks things again, unless you create an implicit conversion for each type in the Writes type class.

于 2012-10-31T08:20:44.097 回答