我一直在阅读有关Dotty的内容,因为看起来它似乎将成为scala 3,并注意到类型预测被视为“不健全”并从语言中移除......
这看起来很糟糕,因为我看到了几个非常有用的用例。例如:
trait Contents
class Foo extends Contents
class Bar extends Contents
trait Container[T <: Contents] { type ContentType = T }
class FooContainer extends Container[Foo]
class BarContainer extends Container[Bar]
trait Manager[T <: Container[_]] {
type ContainerType = T
type ContentType = T#ContentType
def getContents: ContentType
def createContainer(contents: ContentType): ContainerType
}
如何在Dotty中做这样的事情?将第二个类型参数添加到Manager
?但是,除了它使创建和操作Manager
的实例变得非常繁琐之外,它也不太有用,因为没有办法强制执行这两种类型之间的关系({{1不应该是合法的。)
然后,还有其他用途,比如类型lambda和部分应用类型,它们对于创建有偏见的仿函数等很有用......或者这些(部分应用的类型)在Dotty中成为“一等公民”?
编辑
要回答评论中的问题,这里有一个有点人为的例子,可以使用他的这个。我们假设,我的Manager[FooContainer, Bar]
实际上是Akka Managers
:
Actors
答案 0 :(得分:0)
在Scala 2.12中,类型投影有时可以替换为类型类+依赖于路径的类型
trait ContentType[T <: Container[_]] {
type Out
}
object ContentType {
type Aux[T <: Container[_], Out0] = ContentType[T] { type Out = Out0 }
def instance[T <: Container[_], Out0]: Aux[T, Out0] = new ContentType[T] { type Out = Out0 }
implicit def mk[T <: Contents]: Aux[Container[T], T] = instance
}
abstract class Manager[T <: Container[_]](implicit val contentType: ContentType[T]) {
type ContainerType = T
def getContents: contentType.Out
def createContainer(contents: contentType.Out): ContainerType
}
在Dotty 0.16.0-bin-20190529-3361d44-NIGHTLY中检入
trait Contents
class Foo extends Contents
class Bar extends Contents
trait Container[T <: Contents] { type ContentType = T }
class FooContainer extends Container[Foo]
class BarContainer extends Container[Bar]
trait ContentType[T <: Container[_]] {
type Out
}
object ContentType {
implied [T <: Contents] for ContentType[Container[T]] {
type Out = T
}
}
trait Manager[T <: Container[_]] given (val contentType: ContentType[T]) {
type ContainerType = T
type ContentType = contentType.Out
def getContents: ContentType
def createContainer(contents: ContentType): ContainerType
}
另一种选择是使用match types
trait Contents
class Foo extends Contents
class Bar extends Contents
trait Container[T <: Contents] { type ContentType = T }
class FooContainer extends Container[Foo]
class BarContainer extends Container[Bar]
type ContentType[T <: Container[_]] = T match {
case Container[t] => t
}
trait Manager[T <: Container[_]] {
type ContainerType = T
def getContents: ContentType[T]
def createContainer(contents: ContentType[T]): ContainerType
}