Можем ли мы определить тождественную функцию более высокого уровня в Scala? - PullRequest
16 голосов
/ 05 сентября 2010

В 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]

но Скалак жалуется, что тип R не найден в RHS.

Есть ли какая-нибудь умная кодировка, которая поможет? Или это просто невозможно сейчас?

Ответы [ 3 ]

13 голосов
/ 05 сентября 2010

X в type HKId[A[X]] = ... - это параметр типа более высокого порядка. Он ограничен предложением параметра типа, на которое обычно ссылаются в ограничении типа. См. §4.4 спецификации:

Вышеуказанные ограничения объема обобщается на случай вложенного типа предложения параметров, которые объявляют параметры типа высшего порядка. Параметры типа высшего порядка (тип параметры типа параметра t) являются видны только их сразу предложение окружающего параметра (возможно в том числе пункты при более глубокой вложенности уровень) и в пределах т. Поэтому их имена должны быть только попарно отличается от имен другие видимые параметры. Поскольку имена параметров типа высшего порядка Таким образом, часто не имеют значения, они могут быть обозначается символом «_», что нигде виден.

Некоторое время назад мы обсуждали возможность добавления буквального синтаксиса для функций типа, например, [A] Either[Int, A]. Это было бы действительно полезно в Скалазе. Тем временем мы используем трюк из ответа Алексея, выраженный в чертах PartialApplyXofY . Вывод был бы еще лучше, но это гораздо сложнее, несмотря на безобидную запись в Trac !)

Так или иначе, во время этой темы Адриан упомянул :

Это, очевидно, не будет тривиальным реализовать все, что логично следует из наличия анонимного типа функции, как у нас в настоящее время нет необходимая инфраструктура, чтобы позволить люди, чтобы написать более доброго типа псевдонимы, например:

type MyTypeFun = [X, Y] Pair [Y, X] // желательно, но трудно поддерживать текущая реализация (мы смотрим на параметры типа символа для вывода своего рода)

UPDATE

Оказывается, вы уже можете подойти довольно близко:

def hk[_[_]] = (); 
hk[({type A[X] = X})#A]

Или немного креатива:

def hk[_[_]] = (); hk[({type \[X] = X}) # \ ]
def hk[_[_]] = (); hk[({type λ[α]=α})#λ ]
5 голосов
/ 05 сентября 2010

Не могу найти способ сделать это как 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]
3 голосов
/ 13 ноября 2011

Кажется немного несправедливым вырвать правильный ответ из @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

Я неконечно, почему это кажется очевидным сейчас, но не было очевидным год назад ... возможно, потому что мы все с тех пор привыкли видеть лямбды типа.

...