【发布时间】:2020-08-14 06:27:20
【问题描述】:
我想提取一个 kind 的类型,并用它来定义一个函数的返回类型。
例如。
让我们定义一个Container 特征。
trait Container[T] {
def contained: T
}
让我们定义一个Extra trait,这样我们就可以从我们的容器中扩展它。
trait Extra[T] {
def extra: T
}
让我们将特征ContainerExtractor 定义为
trait ContainerExtractor[T, C <: Container[T]] {
def extract(container: C): T
}
现在用户可以通过以下方式实现ContainerExtractor
new ContainerExtractor[String, Container[String] with Extra[Int]] {
override def extract(container: Container[String] with Extra[Int]): String = ???
}
不错,虽然用户需要在Container 中声明类型两次!
[String, Container[String] ... ]
为了解决这个重复问题,我尝试通过将Container 和ContainerExtractor 重新定义为
trait Container[T] {
def contained: T
final type Contained = T
}
trait ContainerExtractor[C <: Container[_]] {
def extract(container: C): C#Contained
}
这样(我希望)想要实现ContainerExtractor 的用户可以这样写:
new ContainerExtractor[Container[String] with Extra[Int]] {
override def extract(container: Container[String] with Extra[Int]): String =???
}
虽然这失败了:
incompatible type in overriding
def extract(container: Test.Container[String] with Test.Extra[Int]): _$2 (defined in trait ContainerExtractor);
found : (container: Test.Container[String] with Test.Extra[Int])String
required: (container: Test.Container[String] with Test.Extra[Int])_$2
因为编译器无法推断出C <: Container[_] 中通配符引用的类型在此特征实现中是String。
在实现ContainerExtractor 时如何避免让用户定义容器类型两次的任何帮助?
【问题讨论】:
标签: scala types traits type-alias higher-kinded-types