上下文界定中的高等类型的快捷方式
上下文界定中的高等类型的快捷方式
是否可能在高阶类类型中使用上下文界定语法快捷方式?
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...
admin 更改状态以发布 2023年5月22日
注意,implicitly [ClassManifest [List [_]]]
缩写为implicitly [ClassManifest [List [T] forSome {type T}]]
。
这就是它起作用的原因:ClassManifest
需要一个正确的类型参数,List [T] forSome {type T}
是一个正确的类型,但List
是一个类型构造器。(请参见Scala中的高种类型是什么?以获取“proper”等定义。)
为了使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][* -> *]
)
是的,但是您的上下文限制类型必须具有更高阶的类型参数(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的类型参数。
更新
为了完整起见,我应该指出,可以使用类型λ内联类型别名,
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]