What does Dotty offer to replace type projections?

后端 未结 1 773
广开言路
广开言路 2021-01-14 03:41

I have been reading about Dotty, since it looks like it is about to become scala 3, and noticed that type projections are deemed \"unsound\" and removed from the language ..

相关标签:
1条回答
  • 2021-01-14 04:11

    In Scala 2.12 type projections sometimes can be replaced with type class + path-dependent types

    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
    }
    

    Checked in Dotty 0.16.0-bin-20190529-3361d44-NIGHTLY (in 0.16.0-RC3 delegate should be instead of implied)

    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
    }
    

    One more option is to use 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
    }
    
    0 讨论(0)
提交回复
热议问题