用类型构造函数扩展类

问题描述

我正在尝试使用单个[A]类型参数和带有A [_]类型参数的子类扩展基类-像这样:

abstract class IsBase[A]

abstract class IsSub[A[_]] extends IsBase[A[_]] {
  type T
  def get(self: A[T]): T 
}

implicit def listIsSub[_T] = new IsSub[List] {
  type T = _T;
  def get(self: List[T]): T = self(0)
}
val list = List(1,2)

implicitly[IsSub[List]{ type T = Int }].get(list) // works fine
implicitly[IsBase[List[Int]]] // Could not find implicit value for parameter e

我知道一种实现此目的的方法就是将抽象类型T移至类型参数,例如:

abstract class IsSub1[A[_],T] extends IsBase[A[T]]

但是在我继续这条路线之前,我想先检查一下,没有一种直接的方法可以使它按原样进行。

谢谢!

解决方法

您应该尝试的the first things之一是手动解决隐式问题,然后看看会发生什么情况

implicitly[IsBase[List[Int]]](listIsSub[Int])

//type mismatch;
// found   : App.IsSub[List]{type T = Int}
// required: App.IsBase[List[Int]]
//Note: List[_] >: List[Int] 
// (and App.IsSub[List]{type T = Int} <: App.IsBase[List[_]]),//  but class IsBase is invariant in type A.
//You may wish to define A as -A instead. (SLS 4.5)

因此您可以看到您只是没有定义必要的隐式。您定义了类型为IsSub[List]{type T = Int}的隐式变量,该隐式类型未连接到IsBase[List[Int]],因为IsSub(使用类型构造函数类型参数为A[_]的扩展)以存在类型扩展了IsBase[A[_]]参数。存在性(和类型投影)rarely与隐性一起很好地发挥作用。

您可以看到提示。您可以使IsBase成为反变量

abstract class IsBase[-A]

然后

implicitly[IsBase[List[Int]]]

编译。

是否要定义类型类反变(1 2 3 4)取决于您的逻辑。