Я читал о 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
}
Как можно сделать что-то подобное в Дотти? Добавить параметр второго типа в Manager
? Но, помимо того факта, что создание экземпляров Manager
и манипулирование ими становится действительно утомительным, он также не совсем работает, так как нет способа установить связь между двумя типами (Manager[FooContainer, Bar]
не должно быть законным).
Кроме того, существуют другие варианты использования, такие как лямбда-выражения типов и частично применяемые типы, которые полезны для создания предвзятых функторов и т. Д. Или эти (частично применяемые типы) становятся «гражданами первого класса» в Dotty?
ИЗМЕНИТЬ
Чтобы ответить на вопрос в комментариях, вот несколько надуманный пример его этого. Предположим, мои Managers
на самом деле являются Akka Actors
:
abstract class BaseManager[T <: Container[_]](
val storage: ContentStorage[T#ContentType]
) extends Actor with Manager[T] {
def withContents(container: T, content: ContentType): ContainerType
def withoutContents: T
var container: T = withoutContents
def receive: Receive {
case ContentsChanged =>
container = withContents(container, storage.get)
case ContainerRequester =>
sender ! container
// ... other common actions
}
}
class FooManager(storage: FooStorage) extends BaseManager[FooContainer](storage) {
def withContents(container: FooContainer, content: Foo) =
container.copy(Some(content))
def withoutContent = FooContainer(None)
override def receive: Receive = super.receive orElse {
// some additional actions, specific to Foo
}
}
case class FooContainer(content: Option[Foo]) extends Container[Foo]{
// some extremely expensive calculations that happen when
// content is assigned, so that we can cache the result in container
}
storage
, ноFooManager
расширяетBaseManager
без аргументов. - person Guillaume Martres   schedule 30.04.2018Foo-Bar
MCVE не компилируется.Container
имеет общий, а вManager[T <: Container]
он используется без универсального.ContainerType
определяется дважды вManager
. - person Dmytro Mitin   schedule 30.05.2019Error: covariant type ContentType occurs in contravariant position in type Manager.this.ContentType of value content
. Ну, я просто не хочу догадываться, что ты имеешь в виду. - person Dmytro Mitin   schedule 30.05.2019def createContainer[U >: ContentType](contents: U): ContainerType
должно быть вместоdef createContainer(contents: ContentType): ContainerType
. В любом случае, подойдет ли вам мой ответ? - person Dmytro Mitin   schedule 04.06.2019