问题描述
我正在尝试使用单个[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]]]
编译。