1

简短形式:我有一个与 . 签名相同的方法Future.recover。将部分函数传递给Future的版本有效。将相同的 PF 传递给我的版本会导致missing parameter type for expanded function. The argument types of an anonymous function must be fully known. (SLS 8.5)错误。有什么不同?

更长的形式:我正在尝试实现此处TracingFuture讨论的类,以尝试跨未来边界跟踪错误。基本技术是将 Future 包装在另一个类中,同时添加一个伪堆栈跟踪。TracingFuture

博客文章中给出的代码缺少recoverfrom 的方法Future,所以我用相同的签名添加了它:

class TracingFuture[+T](underlying: Future[T], val trace: Vector[FutureTraceElement]) extends Future[T] {

  def recover[U >: T](pf: PartialFunction[Throwable, U]
                     )(implicit ec: ExecutionContext, enclosing: sourcecode.Enclosing, file: sourcecode.File,
                       line: sourcecode.Line): TracingFuture[U] = {
    val recovered = underlying.recover(pf)
    new TracingFuture[U](recovered, trace :+ FutureTraceElement(enclosing.value, "recover", file.value, line.value))

  }

}

为了比较,这是Future. 请注意,除了额外的隐式参数之外,签名是相同的。

trait Future[+T] extends Awaitable[T] {

  def recover[U >: T](pf: PartialFunction[Throwable, U])(implicit executor: ExecutionContext): Future[U] =
    transform { _ recover pf }
}

最后,我产生编译错误的代码:

val x: TracingFuture[Vector[Maintainer]] = ... // code producing a TracingFuture
val fMaintainers = x.recover {
  case err: Throwable ⇒
    logger.error("Failed to get list of user maintainers.", err)
    Vector.empty[Maintainer]
}

和错误信息:

[error] /Users/bwbecker/oat/src/oat3/modules/wapp/app/oat/wapp/dao/CronJobDAO.scala:273: missing parameter type for expanded function
[error] The argument types of an anonymous function must be fully known. (SLS 8.5)
[error] Expected type was: ?
[error]     val fMaintainers = x.recover {
[error]                                  ^

再一次,这段代码适用于,Future.recover但我得到一个编译错误TracingFuture.recover。我不明白为什么。

这个 SO question解释了编译器知道偏函数的参数必须是 T 的超类型,但不能保证。但是为什么它没有遇到这个问题Future.recover呢?

而且,当然,我想知道除了重写匿名部分函数以使类型显式之外,我是否还能做些什么。

4

2 回答 2

2

问题在于它TracingFuture有两个重载recover方法:一个是您添加的,另一个是您从Future. 当您只有一个时,它提供了对类型推断至关重要的预期类型,但是对于重载方法,它不起作用,正如您从Expected type was: ?.

您可能认为编译器应该注意到函数参数的类型是相同的,因此仍然可以提供预期的类型。你是对的,但它只在 Scala 2.12 中修复

当然,你会遇到麻烦,当只有隐式参数不同时,编译器无法判断你想要哪个重载。

于 2018-04-10T21:29:00.283 回答
1

尝试更换

val fMaintainers = x.recover {
  case err: Throwable ⇒
    logger.error("Failed to get list of user maintainers.", err)
    Vector.empty[Maintainer]
}

val fMaintainers = x.recover(PartialFunction[Throwable, Vector[Maintainer]] { 
  case err: Throwable ⇒
    logger.error("Failed to get list of user maintainers.", err)
    Vector.empty[Maintainer]
})

为什么我在一种情况下得到“扩展功能的缺失参数”而不是另一种情况?

于 2018-04-10T21:02:05.410 回答