Можем ли мы определить более высокую функцию идентификации уровня на уровне типа в 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]