Подчеркивание в Scala указывает на экзистенциальный тип, то есть параметр неизвестного типа, который имеет два основных использования:
- Он используется для методов, которые не заботятся о параметре типа
- Он используется для методов, в которых вы хотите выразить, что один параметр типа является конструктором типа.
Конструктор типа - это, по сути, то, что нуждается в параметре типа для создания конкретного типа. Например, вы можете взять следующую подпись.
def strangeStuff[CC[_], B, A](b:B, f: B=>A): CC[A]
Это функция, которая для некоторых CC[_]
, например List[_]
, создает List[A]
, начиная с B, и функцию B=>A
.
Почему это может быть полезно? Что ж, оказывается, если вы используете этот механизм вместе с неявными выражениями и классами типов, вы можете получить то, что называется специальным полиморфизмом, благодаря аргументам компилятора.
Представьте, например, что у вас есть более высокий тип: Container[_]
с иерархией конкретных реализаций: BeautifulContainer[_]
, BigContainer[_]
, SmallContainer[_]
. Чтобы построить контейнер, вам понадобится
trait ContainerBuilder[A[_]<:Container[_],B] {
def build(b:B):A[B]
}
Таким образом, по сути, ContainerBuilder - это то, что для определенного типа контейнера A [_] может построить A [B], используя B.
Хотя это было бы полезно? Что ж, вы можете представить, что у вас может быть функция, определенная где-то еще, например:
def myMethod(b:B)(implicit containerBuilder:ContainerBuilder[A[_],B]):A[B] = containerBuilder.build(b)
А затем в своем коде вы можете сделать:
val b = new B()
val bigContainer:BigContainer[B] = myMethod(b)
val beautifulContainer:BeautifulContainer[B] = myMethod(b)
Фактически, компилятор будет использовать требуемый тип возвращаемого значения myMethod для поиска неявного, который удовлетворяет требуемым ограничениям типа, и выдаст ошибку компиляции, если не существует ContainerBuilder, который неявно соответствует требуемым ограничениям.
person
Edmondo1984
schedule
08.10.2012