Scala中的抽象参数类型

时间:2018-02-21 17:12:32

标签: scala parametric-polymorphism abstract-type

我有:

trait A[B[_]]

我有:

trait Base {
    type AImpl <: ???
    def foo: AImpl
}

这样扩展Base的类将定义A并实现方法和字段。即:

trait BB[T]
trait AA extends A[BB]

trait Child extends Base {
  override type AImpl = AA
}

我的问题是声明抽象类型AImpl。我试过了:

type AImpl <: A[B[_]] forSome {type B[_]}

但是我收到以下编译错误:

B[_] takes no type parameters, expected: one
type AImpl <: A[B[_],_] forSome {type B[_]}

声明这种抽象类型的正确方法是什么?

1 个答案:

答案 0 :(得分:1)

此代码符合您的要求,但我不认为您的意思是这样做:

trait A[B[_]]

trait Base {
  type AImpl <: A[B] forSome { type B[_] }
  def foo: AImpl
}

如果你可以更具体,我可以找出你的问题并提出另一种方法。

正如我之前所坚持的那样,你的意图存在很多问题。我很清楚你正在尝试做一些你不应该做的事情。

要解释几个问题,首先需要了解存在类型。在这里,您使用特定约束来量化AImpl

type AImpl <: A[B] forSome { type B[_] }

这要求其实现符合这种类型。但是,由于

,这种类型不可能有任何实现
  1. B隐藏在存在类型中,因此在外面是未知的;
  2. A是不变的,因此它强制实现为A[B]的子类型,用于完全隐藏的B
  3. 这两个一起禁止AImpl实现。修复它的方法是转换A协变:

    trait A[+B[_]]
    
    trait Base {
      type AImpl <: A[B] forSome { type B[_] }
      def foo: AImpl
    }
    
    trait BB[T]
    trait AA extends A[BB]
    
    object Child extends Base {
      override type AImpl = A[BB]
    
      def foo = ???
    }
    

    此代码编译没有问题。

    然而,我不得不说存在量化B是一个根本上有缺陷的想法,因为在给定的环境中,如果你需要它,就没有类型安全的方法来恢复B了更不用说scala中更高级的kinded类型是不够的和不正确的。