证明一个抽象类型实现了一个类型类



我相信我对此的理解是正确的,但我想核实一下。在创建类型类时,让它们采用单个类型参数(如TypeClass[A](会感觉更整洁。如果typeclass需要以其他方式进行参数化,则可以使用抽象类型,这里对这两种方法进行了比较:抽象类型与类型参数

据我所知,链接中没有提到的一件事是,如果使用类型参数,你可以看到该参数实现了一个(不同的(类型类,比如:

trait IsValidForTC[A]

abstract class TCWithTypeParam[A, B] (implicit ev: IsValidForTC[B]) {} 

如果我使用抽象类型,我不能确定它是否实现了IsValidForTC:

abstract class TCWithAbstractType[A] (implicit ev: IsValidForTC[B]) {
type B
} //not found: Type B

如果是这样,那么这是有道理的,但上面的链接中没有提到这个差异,所以我想检查一下。

谢谢!

您可以选择是在类级别还是方法级别上设置隐式约束。这会影响隐词的解析时间。

在具有隐式参数的类型参数类型类中,您不约束类型类的类型(应用于类型参数(,即即使作用域中没有隐式IsValidForTC[B],也可以使用类型TCWithTypeParam[A, B]。您所约束的是类型类的构造函数。您可以通过以下方式模拟类型成员类型类的这种行为。使构造函数私有化,并在具有所需隐式约束的伴随对象中定义apply方法(有时称为instance(

abstract class TCWithAbstractType[A] private {
type B
}
object TCWithAbstractType {
def apply[A, _B: IsValidForTC]: TCWithAbstractType[A] { type B = _B } = 
new TCWithAbstractType[A] { type B = _B }
}

您可以添加见证,但它需要在类范围内,这样它才能访问B:

abstract class TCWithAbstractType[A] {
type B
implicit val ev: IsValidForTC[B]
}

但在实践中,这通常不如类型参数方便,因为它必须显式实现,比如

new TCWithAbstractType[A] {
type B = ...
implicit val ev: IsValidForTC[B] = ...
}

而构造函数参数只是从外部作用域获取隐式值。

注意:这是我对你后续问题的部分重复回答,但请留在这里,以防有人先发现这个问题。

最新更新