[英]Constraining Higher-Kinded Types in Scala
说我有更高的kinded类型
SuperMap[Key[_],Value[_]]`.
假设我现在有一些更具体的东西,要求Key
的type参数必须与Value
匹配; 就是这样的:
SuperDuperMap[T, Key[T], Value[T]]
进一步假设我不想要任何T
,而是一个非常具体的T <: OtherT
SuperDuperPooperMap[T <: OtherT, Key[T], Value[T]]
这可以在Scala中完成吗? 这通常是一个坏主意吗? 有没有一种相同的方法可以更容易地读/写/使用?
你的声明已经按照预期的方式工作,即你限制了T
的类型以及Key
和Value
。 然而,如果你发布类似的东西,scala会抱怨你的方式
scala> class Foo[T <: OtherT, Key[T], Value[T]]
defined class Foo
scala> new Foo[SpecialOtherT, Key[SpecialOtherT], Value[SpecialOtherT]]
<console>:13: error: Key[SpecialOtherT] takes no type parameters, expected: one
new Foo[SpecialOtherT, Key[SpecialOtherT], Value[SpecialOtherT]]
因为您的前声明已经给出了Key
和Value
的类型。 因此,这将有效
scala> new Foo[SpecialOtherT, Key, Value]
res20: Foo[SpecialOtherT,Key,Value] = Foo@3dc6a6fd
这可能不是你想要的。 你可以这样做
scala> class Foo[T <: OtherT, K <: Key[T], V <: Value[T]]
defined class Foo
scala> new Foo[SpecialOtherT, Key[SpecialOtherT], Value[SpecialOtherT]]
res21: Foo[SpecialOtherT,Key[SpecialOtherT],Value[SpecialOtherT]] = Foo@7110506e
在底线,由于Key
和Value
的类型完全取决于T
因此在使用Foo
时获得所有冗余信息有点多余。 那么为什么不使用这样的内部类型声明:
class Foo[T <: OtherT] {
type K = Key[T]
type V = Value[T]
}
然后,您可以从类中访问类型K
和V
,但每次创建新答案时都不需要键入它:
scala> new Foo[SpecialOtherT]
res23: Foo[SpecialOtherT] = Foo@17055e90
scala> new Foo[Int]
<console>:11: error: ...
这可以在Scala中完成吗?
你什么意思? 你刚才做到了!
这通常是一个坏主意吗?
为什么会这样? 事实上,这是一个好主意! 这就是高等级的类型。
有没有一种相同的方法可以更容易地读/写/使用?
阅读 - 对我来说很好看。
写 - 写/测试/编译一次,到处使用。
使用 - 编译器将重建(推断)“无处不在”的类型。
您可能不需要比几个类型别名更复杂的东西,
type SuperDuperMap[T, Key[_], Value[_]] = SuperMap[Key, Value]
type SuperDuperPooperMap[T <: OtherT, Key[_], Value[_]] = SuperMap[Key, Value]
示例REPL会话,
scala> new SuperDuperMap[Int, Option, List] {}
res0: java.lang.Object with SuperDuperMap[Int,Option,List] = ...
scala> new SuperDuperPooperMap[OtherT, Option, List] {}
res1: java.lang.Object with SuperDuperPooperMap[OtherT,Option,List] = ...
声明:本站的技术帖子网页,遵循CC BY-SA 4.0协议,如果您需要转载,请注明本站网址或者原文地址。任何问题请咨询:yoyou2525@163.com.