2010-09-05 2 views
15

В Scala мы можем определить функцию тождества типа уровня для более низкого kinded типов, как это так,Можем ли мы определить высокоуровневую идентификационную функцию уровня в Scala?

type Id[A] = A 

Может ли мы также определить что-то подобное для высокодоходных kinded типов? То есть. мы можем заполнить пробелы в,

type HKId[A[...]] = ... 

так, что-то похожее на HKId [Список] возвращает нас к конструктору типа списка?

Связывание свободных имен в таких вещах, как,

type Foo[X] = List[X] 
val l : Foo[Int] = List(1, 2, 3) 

может привести нас ожидать, что идентичность высшего kinded уровень типа будет выглядеть,

type HKId[A[X]] = A[X] 

но scalac жалуется, что тип X не найден на RHS.

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

+0

Не могу проверить, но что из себя: HKId [A [_]] = A' – Dario

+0

+1 для того, чтобы моя голова взорвалась – delnan

+0

@ Dario No ... "error: type A принимает параметры типа" на RHS. –

ответ

3

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

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

+0

Да, это кажется очевидным, как только вы его видите! –

5

Не можете найти способ сделать это как 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] 
+0

Как я упоминал в своем комментарии к ответу Джейсона, я хочу иметь возможность сделать это как тип. Поэтому ваш ответ, что это невозможно сделать так, тоже правильно. Благодарю. –

+0

Собственно, при ближайшем рассмотрении это в значительной степени то, что я теперь называю правильным ответом ... Единственное различие между вашим и моим заключается в том, что я заменил 'type' для' class'. –

12

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

The above scoping restrictions are generalized to the case of nested type parameter clauses, which declare higher-order type parameters. Higher-order type parameters (the type parameters of a type parameter t) are only visible in their immediately surrounding parameter clause (possibly including clauses at a deeper nesting level) and in the bounds of t . Therefore, their names must only be pairwise different from the names of other visible parameters. Since the names of higher-order type parameters are thus often irrelevant, they may be denoted with a ‘_’, which is nowhere visible.

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

Во всяком случае, во время этого потока, Adriaan mentioned:

It obviously won't be trivial to implement everything that logically follows from having anonymous type functions, as we currently don't have the necessary infrastructure to allow people to write higher-kinded type aliases, for example:

type MyTypeFun = [X, Y] Pair[Y, X] // desirable, but hard to support with the current implementation (we look at the type params of a symbol to infer its kind)

UPDATE

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

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

Или получить немного креатива:

def hk[_[_]] =(); hk[({type \[X] = X}) # \ ] 
def hk[_[_]] =(); hk[({type λ[α]=α})#λ ] 
+0

Он делает это как тип, который мне нужен (я знаю об особенностях Scalaz PartialApply), и почта Адриана дает понять, что это невозможно ... спасибо за указатель. –

Смежные вопросы