是否可以将上下文边界语法快捷方式用于更高种类的类型?
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...
是否可以将上下文边界语法快捷方式用于更高种类的类型?
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...
是的,但是您的上下文绑定类型必须具有更高种类的类型参数(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 中的高级类型? )
为了使两者都能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][* -> *]
)