2011-04-04 21 views
10
ile kısayol

o bağlamı kullanmak mümkün mü yüksek kinded-türleriyle sözdizimi kısayol bağlamıştır?Bağlam sınırları yüksek kinded-tipleri

trait One { def test[W : ClassManifest]: Unit } // first-order ok 
trait Two { def test[W[_]: ClassManifest]: Unit } // not possible?? 
trait Six { def test[W[_]](implicit m: ClassManifest[W[_]]): Unit } // hmm... 

cevap

11

Evet, öyle, ama bağlamla sınırlı tip yüksek kinded tür parametresi (ClassManifest değil ki) olması gerekir.

scala> trait HKTypeClass[CC[_]] 
defined trait HKTypeClass 

scala> implicit def listHKTC = new HKTypeClass[List] {} 
listHKTC: java.lang.Object with HKTypeClass[List] 

scala> def frob[CC[_] : HKTypeClass] = implicitly[HKTypeClass[CC]] 
frob: [CC[_]](implicit evidence$1: HKTypeClass[CC])HKTypeClass[CC] 

scala> frob[List] 
res0: HKTypeClass[List] = [email protected] 

Güncelleme

Bu, daha kinded tür parametresi birinci dereceden bir bağlam bağlanmış türü ile sınırlı izin vermek için bir tür diğer adı kullanmak mümkündür. İlk sıra türünden daha iyi bir tür oluşturmak için tür takma adını tür düzeyinde bir işlev olarak kullanırız. ClassManifest için bu, böyle tip takma CC [_] sağ taraftaki birinci dereceden türü olduğunu

scala> type HKClassManifest[CC[_]] = ClassManifest[CC[_]] 
defined type alias HKClassManifest 

scala> def frob[CC[_] : HKClassManifest] = implicitly[HKClassManifest[CC]]   
test: [CC[_]](implicit evidence$1: HKClassManifest[CC])HKClassManifest[CC] 

scala> frob[List]              
res1: HKClassManifest[List] = scala.collection.immutable.List[Any] 

Not gidebiliriz ... Burada alt çizgi joker olduğunu. Sonuç olarak, ClassManifest için tip argümanı olarak kullanılabilir.

Güncelleme tamlığı ben tip takma bir tip lambda kullanarak satır içine yerleştirilmiş olabilir dikkat etmelisiniz için

, implicitly[ClassManifest[List[_]]]implicitly[ClassManifest[List[T] forSome {type T}]] kısaltmasıdır

scala> def frob[CC[_] : ({ type λ[X[_]] = ClassManifest[X[_]] })#λ] = implicitly[ClassManifest[CC[_]]]  
frob: [CC[_]](implicit evidence$1: scala.reflect.ClassManifest[CC[_]])scala.reflect.ClassManifest[CC[_]] 

scala> frob[List] 
res0: scala.reflect.ClassManifest[List[_]] = scala.collection.immutable.List[Any] 
+0

Ancak 'bu sürece daha yüksek türleri (hatta Joker ile) bağlı olarak tahmin daha ClassManifest' onun tür parametresi kendisi daha yüksek kinded olduğu hakkında bilgi gerekli değildir, örneğin, neden def testi değil [A, B [A]: ClassManifest] {}, 'def testi [A, B [A]] olmasına rağmen (örtük m: ClassManifest [B [A]]) {} ' ? –

+0

ClassManifest o tip argümanı sen repl içinde örtük [ClassManifest [Liste]] çalışırsanız gördüğünüz gibi birinci dereceden olduğunu gerektirir. –

+0

Demek istediğim budur: ilk argümana indirgenmiş olduğu sürece arg türünün birinci sırada mı yoksa daha yüksek mi olduğunu anlamsızdır: örtük [ClassManifest [Liste [_]]] '-> tamam ! Bu yüzden neden bu bağlamda bir bağlam için kısayolu alamıyorum diye merak ediyordum –

4

Not söyledi. ClassManifest uygun bir tip argümanlar bekler ve List[T] forSome {type T} uygun bir türüdür fakat List bir tür yapıcı: işliyor neden

budur.

:

hem ClassManifest[List[String]] ve ClassManifest[List] işi yapmak için, değişen türlü tip parametrelerini almak sürümleri gibi bir şey ile bir şekilde ClassManifest aşırı gerekiyordu (vs. "doğru" tanımı için What is a higher kinded type in Scala? bakınız)

class ClassManifest[T] // proper type 
class ClassManifest[T[_]] // type constructor with one type parameter 
class ClassManifest[T[_, _]] // type constructor with two type parameters 
// ... ad nauseam 
(akademik not olarak, bunu yapmak için "doğru" yolda, fazla çeşit soyutlama izin olacaktır:

class ClassManifest[T : K][K] 

    implicitly[ClassManifest[String]] // --> compiler infers ClassManifest[String][*] 
    implicitly[ClassManifest[List]] // --> compiler infers ClassManifest[List][* -> *] 

)