2010-09-05 1 views
15

In Scala possiamo definire la funzione di legittimazione a livello per i tipi bassi-kinded come così,È possibile definire una funzione di identità di livello superiore di tipo superiore in Scala?

type Id[A] = A 

Possiamo anche definire qualcosa di simile per i tipi più elevati-kinded? Vale a dire. possiamo riempire gli spazi vuoti in,

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

in modo che qualcosa di simile a HKId [Elenco] noi torna al costruttore Il tipo di lista?

Il legame di nomi gratuiti a cose come,

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

ci indurrebbe ad attendersi che un'identità superiore kinded tipo di livello sarà simile,

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

ma scalac lamenta che tipo X non è stato trovato sul RHS.

C'è qualche codifica intelligente che farà il trucco? O semplicemente non è possibile in questo momento?

+0

Non può provare, ma ciò che abot 'HKId [A [_]] = A' – Dario

+0

+1 per aver reso la mia testa esplodere – delnan

+0

@Dario No ... "Errore: tipo A prende parametri di tipo" sul RHS. –

risposta

3

Mi sembra un po 'ingiusto per strappare la risposta corretta da @retronym, ma sembra che siamo in grado di ottenere un po' più vicino al tipo di soluzione che cercavo,

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 

I' Non sono sicuro del perché questo sembra ovvio ora, ma non era ovvio un anno fa ...forse perché siamo diventati molto più abituati a vedere il tipo lambda da allora.

+0

Sì, sembra ovvio una volta che lo vedi! –

5

non riesco a trovare un modo per farlo come un type, ma questo funziona:

class HKId[A[_]] { 
    type Value[X] = A[X] 
} 

Questo compila:

scala> List(1): HKId[List]#Value[Int] 
res2: List[Int] = List(1) 

E questo non lo fa:

scala> List(1): HKId[List]#Value[Boolean] 
<console>:7: error: type mismatch; 
found : Int(1) 
required: Boolean 
     List(1): HKId[List]#Value[Boolean] 
+0

Come ho detto nel mio commento sulla risposta di Jason, voglio essere in grado di farlo come un tipo. Quindi la tua risposta che non può essere fatta in questo modo è giusta. Grazie. –

+0

In realtà, a un'osservazione più attenta, questo è praticamente ciò che ora definirei una risposta corretta ... l'unica differenza tra la tua e la mia è che ho sostituito 'type' per' class'. –

12

X in type HKId[A[X]] = ... è un parametro di tipo ordine superiore. È circoscritto alla clausola del parametro type, di solito a cui fa riferimento un vincolo di tipo. Vedere § 4.4 della specifica:

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.

Qualche tempo fa, abbiamo discusso la possibilità di aggiungere una sintassi letterale per funzioni di tipo, ad esempio [A] Either[Int, A]. Questo sarebbe davvero utile in Scalaz. Nel frattempo, utilizziamo il trucco della risposta di Alexey, espressa nello PartialApplyXofY traits. Inference sarebbe ancora meglio, ma questo è molto più difficile, nonostante la innocuous entry in Trac)

In ogni caso, durante quel filo, 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

scopre che può arrivare molto vicino già :

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

Oppure un po 'di creatività:

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

Lo sta facendo come un tipo di quello che sto cercando (sono a conoscenza dei tratti Scalial di PartialApply) e la posta di Adriaan chiarisce che non può essere fatto ... grazie per il puntatore. –