Как преобразовать универсальный метод в универсальную функцию

Вопрос

Как преобразовать метод, рассчитанный по времени, в функцию?

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
}

2 ответа

Решение

В Scala нет такой вещи, как универсальная функция (и вообще универсального значения), есть только универсальные методы.

Стандартные функции появятся в Scala 3.

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

http://dotty.epfl.ch/docs/reference/overview.html

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.

В Scala нет полиморфных функций.

Позвольте мне использовать пример из отличного сообщения в блоге Майлза Сабина:

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()получает ет вспененную в функцию в точке использования, и в этот момент его типы фиксируются в выведенные тип бетона. Таким образом, он может легко "стать" (быть расширен) функциейInt => Set[Int] или String => Set[String], но не может оставаться что-то вроде T => Set[T]. В самом языке нет встроенного способа выражения полиморфных функций (Scala 3 может это изменить).

Тем не менее, есть способ, чтобы иметь полиморфные функции через естественные преобразования и / или бесформенныеPolyс немного типовой гимнастикой. Оба основаны на одном и том же принципе кодирования функции как признака с более высокими типами для ввода / вывода и имеющими общийapply[T]() метод с независимым типом T который фиксируется к другому конкретному типу каждый раз при вызове функции (в нашем случае это были бы Int, String так далее.).

Что-то вроде этого:

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

Но вместо того, чтобы пытаться подробно объяснить это здесь, я бы предпочел отослать вас к бесформенной документации и вышеупомянутой короткой серии сообщений в блогах.

Другие вопросы по тегам