Можем ли мы определить более высокую функцию идентификации уровня на уровне типа в Scala?
В Scala мы можем определить функцию тождества уровня типа для типов с низким уровнем, например,
type Id[A] = A
Можно ли определить что-то подобное для типов более высокого уровня? То есть. можем ли мы заполнить пробелы,
type HKId[A[...]] = ...
так что что-то похожее на HKId [List] возвращает нас к конструктору типа List?
Связывание свободных имен в таких вещах, как
type Foo[X] = List[X]
val l : Foo[Int] = List(1, 2, 3)
Возможно, мы ожидаем, что будет выглядеть более высокоподобная идентичность на уровне типа,
type HKId[A[X]] = A[X]
но scalac жалуется, что тип X не найден в RHS.
Есть ли какая-то умная кодировка, которая будет делать трюк? Или это просто невозможно сейчас?
Ответы
Ответ 1
Кажется немного несправедливым вырвать правильный ответ от @retronym, но похоже, что мы можем немного приблизиться к тому решению, которое было после,
scala> type HKId[A[_]] = { type λ[X] = A[X] }
defined type alias HKId
scala> def foo[C[_]] : C[Int] = null.asInstanceOf
foo: [C[_]]=> C[Int]
scala> foo[List]
res0: List[Int] = null
scala> foo[HKId[List]#λ]
res1: List[Int] = null
Я не уверен, почему это кажется очевидным сейчас, но не было очевидным год назад... возможно, потому что мы все больше привыкли видеть тип lambdas с тех пор.
Ответ 2
X
in type HKId[A[X]] = ...
- параметр более высокого порядка. Он привязан к предложению параметра типа, обычно упоминаемому в типе ограничения. См. П. 4.4 спецификации:
Приведенные выше ограничения могут обобщенный на случай вложенного типа параметрические предложения, объявляющие параметры более высокого порядка. Параметры типа более высокого порядка (тип параметры параметра типа t) являются видны только в их окружающего параметра (возможно включая предложения при более глубоком вложении уровня) и в пределах t. Поэтому их имена должны быть попарно отличается от имен другие видимые параметры. Поскольку имена параметров более высокого порядка таким образом, часто несущественны, они могут быть обозначается символом '_, который нигде видны.
A назад, мы обсудили возможность добавления литерального синтаксиса для функций типа, например. [A] Either[Int, A]
. Это было бы действительно полезно в Scalaзе. Тем временем мы используем трюк от ответа Алексея, выраженный в свойства PartialApplyXofY. Вывод будет еще лучше, но это намного сложнее, несмотря на безобидная запись в Trac!)
В любом случае, во время этой темы Adriaan упоминается:
Очевидно, что это не будет тривиально реализовать все, что логически следует из анонимного типа функций, поскольку у нас в настоящее время нет необходимую инфраструктуру для люди пишут более высокого типа псевдонимы, например:
type MyTypeFun = [X, Y] Пара [Y, X]// желательно, но трудно поддерживать текущая реализация (мы смотрим на параметры типа символа для вывода его вид)
UPDATE
Оказывается, вы уже можете приблизиться:
def hk[_[_]] = ();
hk[({type A[X] = X})#A]
Или немного творческий:
def hk[_[_]] = (); hk[({type \[X] = X}) # \ ]
def hk[_[_]] = (); hk[({type λ[α]=α})#λ ]
Ответ 3
Невозможно найти способ сделать это как type
, но это работает:
class HKId[A[_]] {
type Value[X] = A[X]
}
Это компилируется:
scala> List(1): HKId[List]#Value[Int]
res2: List[Int] = List(1)
И это не так:
scala> List(1): HKId[List]#Value[Boolean]
<console>:7: error: type mismatch;
found : Int(1)
required: Boolean
List(1): HKId[List]#Value[Boolean]