首页 文章

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

提问于
浏览
7

说我有更高的kinded类型

SuperMap[Key[_],Value[_]]`.

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

SuperDuperMap[T, Key[T], Value[T]]

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

SuperDuperPooperMap[T <: OtherT, Key[T], Value[T]]

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

3 回答

  • 2

    您的声明已经按预期工作,即您正在限制 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]]
    

    因为你以前的声明已经给出了 KeyValue 的类型 . 因此,这将有效

    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
    

    在底线,由于 KeyValue 的类型完全取决于 T ,因此在使用 Foo 时获取所有冗余信息有点多余 . 那么为什么不使用这样的内部类型声明:

    class Foo[T <: OtherT] {
      type K = Key[T]
      type V = Value[T]
    }
    

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

    scala> new Foo[SpecialOtherT]
    res23: Foo[SpecialOtherT] = Foo@17055e90
    
    scala> new Foo[Int]
    <console>:11: error: ...
    
  • 11

    这可以在Scala中完成吗?

    你什么意思?你刚才做到了!

    这通常是一个坏主意吗?

    为什么会这样?事实上,这是一个好主意!这就是高等级的类型 .

    有没有一种相同的方法可以更容易地读/写/使用?

    Reading - 对我来说很好看 .

    Writing - 编写/测试/编译一次,随处使用 .

    Using - 编译器将重建(推断)类型"everywhere" .

  • 3

    您可能不需要比几个类型别名更复杂的东西,

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

相关问题