#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