见证一个抽象类型实现了一个类型类
Witness that an abstract type implements a typeclass
我相信我对此的理解是正确的,但我想核实一下。创建类型类时,让它们采用单个类型参数感觉更整洁,例如 TypeClass[A]
。如果类型类需要通过其他方式参数化,可以使用抽象类型,这里有两种方式的比较:
Abstract types versus type parameters
据我所知,link 中没有提到的一件事是,如果使用类型参数,您可以看到该参数实现了一个(不同的)类型类,喜欢:
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
如果是这样,那么这是有道理的,但是上面的 link 中没有提到这种差异,所以我想检查一下。
谢谢!
您可以选择是在 class 级别还是方法级别设置隐式约束。这会对解析隐含项的时间产生影响。
在带有隐式参数的 type-parameter 类型 class 中,您不限制类型 class 的类型(应用于类型参数),即类型 TCWithTypeParam[A, B]
可以即使范围内没有隐式 IsValidForTC[B]
也可以使用。你做的约束是class类型的构造函数。您可以通过以下方式为 type-member type class 模拟此行为。将构造函数设为私有并在具有所需隐式约束的伴随对象中定义 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 }
}
您可以添加见证,但它需要在 class 范围内,以便它可以访问 B
:
abstract class TCWithAbstractType[A] {
type B
implicit val ev: IsValidForTC[B]
}
但实际上这通常不如类型参数方便,因为它必须显式实现,比如
new TCWithAbstractType[A] {
type B = ...
implicit val ev: IsValidForTC[B] = ...
}
而构造函数参数只是从外部范围获取隐式值。
注意:这是我对 的回答的部分重复,但留在这里以防有人首先偶然发现这个问题。
我相信我对此的理解是正确的,但我想核实一下。创建类型类时,让它们采用单个类型参数感觉更整洁,例如 TypeClass[A]
。如果类型类需要通过其他方式参数化,可以使用抽象类型,这里有两种方式的比较:
Abstract types versus type parameters
据我所知,link 中没有提到的一件事是,如果使用类型参数,您可以看到该参数实现了一个(不同的)类型类,喜欢:
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
如果是这样,那么这是有道理的,但是上面的 link 中没有提到这种差异,所以我想检查一下。
谢谢!
您可以选择是在 class 级别还是方法级别设置隐式约束。这会对解析隐含项的时间产生影响。
在带有隐式参数的 type-parameter 类型 class 中,您不限制类型 class 的类型(应用于类型参数),即类型 TCWithTypeParam[A, B]
可以即使范围内没有隐式 IsValidForTC[B]
也可以使用。你做的约束是class类型的构造函数。您可以通过以下方式为 type-member type class 模拟此行为。将构造函数设为私有并在具有所需隐式约束的伴随对象中定义 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 }
}
您可以添加见证,但它需要在 class 范围内,以便它可以访问 B
:
abstract class TCWithAbstractType[A] {
type B
implicit val ev: IsValidForTC[B]
}
但实际上这通常不如类型参数方便,因为它必须显式实现,比如
new TCWithAbstractType[A] {
type B = ...
implicit val ev: IsValidForTC[B] = ...
}
而构造函数参数只是从外部范围获取隐式值。
注意:这是我对