在Scala中约束更高层次的类型

duc*_*thd 7 types scala

说我有更高的kinded类型

SuperMap[Key[_],Value[_]]`.  
Run Code Online (Sandbox Code Playgroud)

现在假设我有一些更具体的东西,要求type参数Key必须匹配Value; 就是这样的:

SuperDuperMap[T, Key[T], Value[T]]
Run Code Online (Sandbox Code Playgroud)

进一步假设我不想要任何一个T,而是一个非常具体的地方T <: OtherT

SuperDuperPooperMap[T <: OtherT, Key[T], Value[T]]
Run Code Online (Sandbox Code Playgroud)

这可以在Scala中完成吗?这通常是一个坏主意吗?有没有一种相同的方法可以更容易地读/写/使用?

fot*_*ton 11

你的声明已经按照预期的方式工作,即你限制的类型T以及KeyValue.然而,如果你发布类似的东西,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]]
Run Code Online (Sandbox Code Playgroud)

因为两者的类型KeyValue已经通过你以前的声明中提到.因此,这将有效

scala> new Foo[SpecialOtherT, Key, Value]
res20: Foo[SpecialOtherT,Key,Value] = Foo@3dc6a6fd
Run Code Online (Sandbox Code Playgroud)

这可能不是你想要的.你可以这样做

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
Run Code Online (Sandbox Code Playgroud)

在底线,由于在使用时具有所有冗余信息的类型Key并且Value完全取决于T它是多余的Foo.那么为什么不使用这样的内部类型声明:

class Foo[T <: OtherT] {
  type K = Key[T]
  type V = Value[T]
}
Run Code Online (Sandbox Code Playgroud)

然后,您可以访问类KV类中的类型,但每次创建新答案时都不需要输入类型:

scala> new Foo[SpecialOtherT]
res23: Foo[SpecialOtherT] = Foo@17055e90

scala> new Foo[Int]
<console>:11: error: ...
Run Code Online (Sandbox Code Playgroud)