0

问题

如何将定时方法转换为函数?

val timing = new StringBuffer
def timed[T](label: String, code: => T): T = {
  val start = System.currentTimeMillis()
  val result = code
  val stop = System.currentTimeMillis()
  timing.append(s"Processing $label took ${stop - start} ms.\n")
  result
}

下面导致“错误:未找到:类型 T”

val timing = new StringBuffer
val timed: (String, => T) => T = (label, code) => {
    val start = System.currentTimeMillis()
    val result = code
    val stop = System.currentTimeMillis()
    timing.append(s"Processing $label took ${stop - start} ms.\n")
    result
}
4

2 回答 2

3

Scala 没有多态函数。

让我使用Miles Sabin的一篇优秀博文中的一个例子:

def singleton[T](t: T) = Set(t)

// eta-expanded to Int => Set[Int]
List(1, 2, 3) map singleton

// eta-expanded to String => Set[String]
List("foo", "bar", "baz") map singleton

方法在使用singleton()时被eta 扩展为一个函数,并且在那时它的类型被固定为推断的具体类型。所以它可以很容易地“变成”(被扩展成)一个函数Int => Set[Int]or String => Set[String],但不能保持像T => Set[T]. 语言本身没有表达多态函数的内置方式(Scala 3可能会改变这一点)。

但是,有一种方法可以通过自然变换和/或shapeless以及一些类型的Poly体操来获得多态函数。两者都基于相同的原则,将函数编码为具有更高种类的输入/输出类型的特征,并具有具有apply[T]()独立类型的通用方法,T每次调用函数时都固定为不同的具体类型(在我们的例子中,那些将是IntString)。

像这样的东西:

trait PolymorphicFunction[F[_], G[_]] {
  def apply[T](f: F[T]): G[T]
}

但与其试图在这里详细解释它,我更愿意向您推荐无形的文档和前面提到的短系列博客文章。

于 2019-11-18T22:58:40.743 回答
3

Scala 中没有泛型函数(也没有泛型值),只有泛型方法。

通用函数将出现在 Scala 3 中。

https://github.com/lampepfl/dotty/pull/4672

http://dotty.epfl.ch/docs/reference/overview.html#new-constructs

val timing = new StringBuffer
val timed: [T] => (String, /*=>*/ T) => T = [T] => (label: String, code: /*=>*/ T) => {
  val start = System.currentTimeMillis()
  val result = code
  val stop = System.currentTimeMillis()
  timing.append(s"Processing $label took ${stop - start} ms.\n")
  result
}

在 Dotty 0.20.0-RC1 中。

于 2019-11-18T22:45:28.653 回答