[英]Context bounds shortcut with higher kinded-types
是否可以使用更高kinded類型的上下文邊界語法快捷方式?
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...
是的,它是,但您的上下文綁定類型必須具有更高的kinded類型參數(ClassManifest不具有)。
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] = $anon$1@13e02ed
更新
可以使用類型別名來允許更高級別的類型參數受一階上下文綁定類型的限制。 我們使用類型別名作為類型級函數來從一階類型中創建一個更高級的類型。 對於ClassManifest,它可以像這樣,
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]
請注意,在類型別名CC [_]的右側是一階類型...這里的下划線是通配符。 因此,它可以用作ClassManifest的類型參數。
更新
為了完整性,我應該注意類型別名可以使用類型lambda內聯,
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]
請注意, implicitly[ClassManifest[List[_]]]
是implicitly[ClassManifest[List[T] forSome {type T}]]
。
這就是它的工作原理: ClassManifest
需要一個正確的類型參數, List[T] forSome {type T}
是一個合適的類型,但List
是一個類型構造函數。 (請參閱Scala中什么是更高級的kinded類型?有關“正確”的定義等)
為了使ClassManifest[List[String]]
和ClassManifest[List]
工作,我們需要以某種方式重載ClassManifest
,其版本采用不同類型的類型參數,如:
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
(在學術說明中,“正確”的方法是允許抽象的類型:
class ClassManifest[T : K][K]
implicitly[ClassManifest[String]] // --> compiler infers ClassManifest[String][*]
implicitly[ClassManifest[List]] // --> compiler infers ClassManifest[List][* -> *]
)
聲明:本站的技術帖子網頁,遵循CC BY-SA 4.0協議,如果您需要轉載,請注明本站網址或者原文地址。任何問題請咨詢:yoyou2525@163.com.