简体   繁体   English

使用类型构造函数扩展类

[英]Extending a class with a type constructor

I'm trying to extend a base class with a single [A] type parameter, with a subclass that has an A[_] type parameter - like this:我正在尝试使用单个 [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

I understand one way to do this would just be to move the abstract type T up to a type parameter, likeso:我知道这样做的一种方法就是将抽象类型 T 向上移动到类型参数,如下所示:

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

But before I go ahead with this route I'd just like to check that there isn't a straightforward way to make this work as it is.但在我继续这条路线之前,我只想检查一下,没有一种直接的方法可以使这项工作正常进行。

Thanks!谢谢!

One of the first things you should try is to resolve the implicit manually and see what will happen您应该尝试的第一件事是手动解决隐式问题,看看会发生什么

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)

So you can see that you just didn't define necessary implicit.所以你可以看到你只是没有定义必要的隐式。 You defined an implicit of type IsSub[List]{type T = Int} , which is not connected to IsBase[List[Int]] because IsSub (with type-constructor type parameter A[_] ) extends IsBase[A[_]] with existential type parameter.您定义了一个类型为IsSub[List]{type T = Int}的隐式,它没有连接到IsBase[List[Int]]因为IsSub (带有类型构造函数类型参数A[_] )扩展了IsBase[A[_]]与存在类型参数。 Existentials (and type projections) rarely play well with implicits.存在(和类型投影)很少与隐式很好地配合。

You can see the hint.你可以看到提示。 You can make IsBase contravariant您可以使IsBase逆变

abstract class IsBase[-A]

Then然后

implicitly[IsBase[List[Int]]]

compiles.编译。

Whether to define your type class contravariant ( 1 2 3 4 ) depends on your logic.是否定义类型类逆变器 ( 1 2 3 4 ) 取决于您的逻辑。

声明:本站的技术帖子网页,遵循CC BY-SA 4.0协议,如果您需要转载,请注明本站网址或者原文地址。任何问题请咨询:yoyou2525@163.com.

 
粤ICP备18138465号  © 2020-2024 STACKOOM.COM