2010-09-05 8 views
15

W Scala możemy zdefiniować funkcję tożsamości typ poziomu dla niższych kinded typów jak tak,Czy możemy zdefiniować w systemie Scala funkcję tożsamości o wyższych poziomach na typie?

type Id[A] = A 

możemy również zdefiniować coś podobnego dla wyższych-kinded typów? To znaczy. możemy wypełnić luki w,

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

tak, że coś podobnego do HKId [LIST] dostaje nas z powrotem do konstruktora typu listy?

Wiązanie wolnych nazw w takie rzeczy,

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

może prowadzić nas się spodziewać, że tożsamość wyższej kinded typu poziom będzie wyglądać,

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

ale scalac narzeka tego typu X nie znaleziono na RHS.

Czy jest jakieś sprytne kodowanie, które wystarczy? A może po prostu nie jest to możliwe?

+0

Nie można przetestować, ale co za dużo 'HKId [A [_]] = A'' – Dario

+0

+1 dla mojej głowy eksplodować – delnan

+0

@Dario Nie ..." błąd: typ A przyjmuje parametry typu "na RHS. –

Odpowiedz

3

Wydaje się nieco niesprawiedliwe wyrwać poprawną odpowiedź od @retronym, ale wygląda na to możemy się trochę bliżej do takiego rozwiązania miałem potem

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 nie jestem pewien, dlaczego wydaje się to oczywiste, ale nie było oczywiste rok temu ...może dlatego, że od tego czasu wszyscy jesteśmy bardziej przyzwyczajeni do oglądania lambd.

+0

Tak, wydaje się oczywiste, gdy już to zobaczysz! –

5

nie można znaleźć sposób, aby to zrobić jako type, ale to działa:

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

To kompiluje:

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

I to nie:

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

Jak wspomniałem w swoim komentarzu do odpowiedzi Jasona, chcę móc to zrobić jako typ. Twoja odpowiedź, że nie można tego zrobić w ten sposób, jest również właściwa. Dzięki. –

+0

Właściwie, po bliższym przyjrzeniu się, jest to coś, co teraz nazywam poprawną odpowiedzią ... jedyną różnicą między twoją i moją jest to, że zastąpiłem 'type' dla' class'. –

12

X w type HKId[A[X]] = ... jest parametrem wyższego rzędu. Jest on ograniczony do klauzuli parametru type, zwykle przywoływanej w ograniczeniu typu. Zobacz: §4.4 specyfikacji:

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.

Niedawno omówiliśmy możliwość dodawania literalnej składni funkcji typu, np. [A] Either[Int, A]. Byłoby to bardzo przydatne w Scalaz. W międzyczasie używamy lewy od odpowiedzi Alexeya, wyrażonej w PartialApplyXofY traits. Wnioskowanie byłoby jeszcze lepiej, ale to znacznie trudniejsze, pomimo innocuous entry in Trac)

Zresztą w tym wątku, 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

Okazuje się, że można dostać już całkiem blisko :

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

Lub uzyskanie trochę kreatywności:

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

Robię to jako typ, którego szukam (jestem świadomy cech PartialApply Scalaza), a poczta Adriaana wyjaśnia, że ​​nie można tego zrobić ... dzięki za wskaźnik. –

Powiązane problemy