我的函数的扩展函数缺少参数类型;不适用于具有相同签名的其他人

时间:2018-04-10 19:33:42

标签: scala lambda pattern-matching function-literal

简短格式:我的方法与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类讨论here,试图追踪未来边界的错误。基本技术是将Future包装在另一个类TracingFuture中,同时添加伪栈跟踪。

博客文章中提供的代码缺少recover的{​​{1}}方法,因此我添加了相同的签名:

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的编译错误。我不明白为什么。

This SO question解释说编译器知道部分函数的参数必须是T的超类型但不能保证。但是为什么它不会遇到TracingFuture.recover的问题?

当然,除了重写匿名部分功能以使类型明确外,我想知道我是否还有其他任何事情。

2 个答案:

答案 0 :(得分:2)

问题是TracingFuture有两个重载的recover方法:您添加的方法和从Future继承的方法。如果只有一个,它提供了对类型推断至关重要的预期类型,但是使用重载方法它不起作用,正如您从Expected type was: ?看到的那样。

您可能认为编译器应该注意到函数参数的类型是相同的,因此仍然可以提供预期的类型。你会是对的,但是it was only fixed in Scala 2.12

当然,如果只有隐式参数不同,那么编译器无法告诉你想要哪个重载会遇到麻烦。

答案 1 :(得分: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]
})

Why do I get a "missing parameter for expanded function" in one case and not the other?