【问题标题】:Scala is not inferring the appropriate methodScala 没有推断出合适的方法
【发布时间】:2012-10-31 07:39:47
【问题描述】:

我有以下方法

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...

【问题讨论】:

  • 需要最小的可重现示例。取决于 IdeaType.find、CrudAuthAction 等的定义。
  • @themel:我认为没有必要发布完整的示例,特别是如果问题得到清晰详细的解释,就像这里一样。

标签: scala generics type-inference


【解决方案1】:

问题在于,在第二个示例中,编译器不知道要选择哪个重载方法,因为 T 很可能是一个函数类型。由于Either 显然不是函数,所以它在第一种情况下有效。

要解决此问题,您可以将第二种方法更改为

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

这样定义 Foo:

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

不幸的是,向 Foo 添加隐式转换又会破坏事情,除非您为 Writes 类型类中的每种类型创建隐式转换。

【讨论】:

  • 让我看看能不能跟着你。你的意思是在这种情况下block:=> T,也可以匹配一个带一个参数的函数,例如{request => ...},所以我应该给编译器更多的线索......
  • 不,我的意思是编译器都知道,T 可能是一个函数类型。
猜你喜欢
  • 1970-01-01
  • 2018-10-21
  • 2017-09-08
  • 1970-01-01
  • 1970-01-01
  • 1970-01-01
  • 2011-12-06
  • 1970-01-01
相关资源
最近更新 更多