Синтаксис Scala для полиморфизма в функциях val

#scala #generics #syntax #functional-programming #polymorphism

#scala #обобщения #синтаксис #функциональное программирование #полиморфизм

Вопрос:

Это потенциально очень просто, но я не могу найти никакой документации по моей проблеме.
Существует два способа определения функций в Scala: один с def помощью, а другой с val ключевым словом. Как специалист в функциональном программировании, я бы хотел больше использовать последнее.

Теперь у меня проблема: написать def функцию с параметром полиморфного типа не проблема:

 def function[T](n: T) = {print(n)} // syntactically fine
 

Однако мне все еще не ясно, как сделать то же самое с val ключевым словом. Этот наивный подход синтаксически недопустим:

 val function[T]: (a: T) => print(a) // Doesn't compile
 

Тем не менее, абсолютно возможно, что я неправильно понимаю подход Scala к полиморфизму и дженерикам здесь.

Комментарии:

1. На самом деле первое утверждение неверно, def создает методы , а не функции . И на самом деле то, что вы просили, — это поиск часто задаваемых вопросов там для «разницы между функциями и методами» _ — TL; DR; то, что вы хотите, невозможно в Scala 2 , но будет в Scala 3 .

Ответ №1:

В Scala 2 невозможно определить параметрическую функцию, только метод.

В Scala 3 введен полиморфный тип функции:

 val fun: [A] => A => Unit = [A] => a => println(a.toString)
 

Обходным путем, используемым в 2 кошками и друзьями, были черты с полиморфным apply

 trait MySpecialFunctionlikeThing {
  def apply[A](a: A): Unit
}
 

К сожалению, единый абстрактный метод (SAM) не работает с подобными вещами, поэтому были использованы некоторые приемы, чтобы упростить перенос функции в такие методы:

 object MySpecialFunctionlikeThing {

  type Arbitrary

  def lift(f: Arbitrary => Unit): MySpecialFunctionlikeThing =
    new MySpecialFunctionlikeThing {
      def apply[A](a: A): Unit = f(a.asInstanceOf[Arbitrary])
    }
}

val fun = MySpecialFunctionlikeThing.lift(a => println(a))
 

Последнее я видел в нескольких разных формах: приведенной выше, использующей экзистенциальные типы и использующей один из приведенных выше для подписи метода и макроса для реализации (см. FunctionK.lift ).

Однако довольно часто вам может сойти с рук то, что вы использовали, это параметрический нулевой метод, возвращающий непараметрическую функцию.

 def fun[A]: A => Unit = a => println(a)
 

Ответ №2:

Для этого потребуются типы более высокого ранга, которые не поддерживаются в Scala 2.

Он поддерживается в Scala 3: https://dotty.epfl.ch/docs/reference/new-types/polymorphic-function-types.html