具有更高种类类型的上下文边界快捷方式

发布于 2024-10-30 06:04:38 字数 276 浏览 2 评论 0原文

是否可以将上下文边界语法快捷方式与更高种类的类型一起使用?

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...

Is it possible to use the context bounds syntax shortcut with higher kinded-types?

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...

如果你对这篇内容有疑问,欢迎到本站社区发帖提问 参与讨论,获取更多帮助,或者扫码二维码加入 Web 技术交流群。

扫码二维码加入Web技术交流群

发布评论

需要 登录 才能够评论, 你可以免费 注册 一个本站的账号。

评论(2

卖梦商人 2024-11-06 06:04:38

是的,确实如此,但是您的上下文绑定类型必须具有更高种类的类型参数(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]

Yes, it is, but your context bound type must have a higher kinded type parameter (which ClassManifest doesn't).

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

Update

It's possible to use a type alias to allow a higher-kinded type parameter to be bounded by a first-order context bound type. We use the type alias as a type-level function to make a higher-kinded type out of the first-order type. For ClassManifest it could go like this,

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]

Note that on the right hand side of the type alias CC[_] is a first-order type ... the underscore here is the wildcard. Consequently it can be used as the type argument for ClassManifest.

Update

For completeness I should note that the type alias can be inlined using a type 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]
秋心╮凉 2024-11-06 06:04:38

请注意,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][* -> *]

:)

Note that implicitly[ClassManifest[List[_]]] is short for implicitly[ClassManifest[List[T] forSome {type T}]].

That's why it works: ClassManifest expects a proper type argument, and List[T] forSome {type T} is a proper type, but List is a type constructor. (Please see What is a higher kinded type in Scala? for a definition of "proper" etc.)

To make both ClassManifest[List[String]] and ClassManifest[List] work, we'd need to overload ClassManifest somehow with versions that take type parameters of varying kinds, something like:

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

(On an academic note, the "proper" way to do this, would be to allow abstracting over kinds:

    class ClassManifest[T : K][K]

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

)

~没有更多了~
我们使用 Cookies 和其他技术来定制您的体验包括您的登录状态等。通过阅读我们的 隐私政策 了解更多相关信息。 单击 接受 或继续使用网站,即表示您同意使用 Cookies 和您的相关数据。
原文