在Scala3中,如果泛型类型参数Map到依赖类型,那么协变和逆变修饰符是如何Map的?

qgelzfjb  于 2023-01-09  发布在  Scala
关注(0)|答案(1)|浏览(149)

本文解释了Scala 3代码中的每个泛型类型参数都被视为依赖类型,以符合DOT逻辑:
https://dotty.epfl.ch/docs/internals/higher-kinded-v2.html
即:
二重性核心思想:参数化类,如
类Map[K,V]
被视为等效于具有类型成员的类型:
类Map{类型Map$K;键入Map$V}
(the文章可能已过时,但设计理念仍应保持不变)
因此,我希望类型参数的任何逆变和协变修饰符也被重写,所以我做了一个快速的实验,编译器应该能够转换以下代码:

object AsArg {

    trait P[+TT] {
      val vv: TT
    }

    trait P1 extends P[Product] {
      val vv: Product
    }
    trait P2 extends P1 with P[Tuple1[Int]] {
      val vv: Tuple1[Int]
    }
  }

变成这样:

object AsDependentType {

    trait P {
      type TT

      val vv: TT
    }

    trait P1 extends P {
      type TT <: Product

      val vv: Product
    }

    trait P2 extends P1 with P {
      type TT <: Tuple1[Int]

      val vv: Tuple1[Int]
    }
  }

具有讽刺意味的是,转换后,编译器抛出以下错误:

[Error] ...CovariantDependentType.scala:30:11: error overriding value vv in trait P of type P1.this.TT;
  value vv of type Product has incompatible type
[Error] ...CovariantDependentType.scala:36:11: error overriding value vv in trait P of type P2.this.TT;
  value vv of type Tuple1[Int] has incompatible type
two errors found

那么转换后正确的等价代码是什么呢?

8wtpewkr

8wtpewkr1#

In/co/contra-variance是类型构造函数F[T]的一个属性。
F是协变的,如果对于所有A <: BF[A] <: F[B]F是反变的,如果对于所有A <: BF[B] <: F[A]F是不变的,如果对于所有A <: BF[A]F[B]<:不相关的。
类型参数和类型成员在Scala 2和Scala 3中是不同的东西。
对于类型参数,可以在申报地点设置差异

trait F[+T] // co-variance
trait F[-T] // contra-variance
trait F[T] // invariance

或在调用位置

trait F[T]
type G[+T] = F[_ <: T] // co-variance
type G[-T] = F[_ >: T] // contra-variance

在Java中没有+/-,所以类型参数的变量必须总是在调用点设置为? extends ...? super ...
对于Scala中的类型成员,也没有+/-,因此必须在调用点设置方差

trait F { type T }
type G[+U] = F { type T <: U } // co-variance 
type G[-U] = F { type T >: U } // contra-variance

类型参数代码

trait P[+TT] {
  val vv: TT
}

trait P1 extends P[Product] {
  val vv: Product
}

trait P2 extends P1 with P[Tuple1[Int]] {
  val vv: Tuple1[Int]
}

可以在Scala 2中转换为类型成员代码,如下所示

trait P {
  type TT
  val vv: TT1 forSome {type TT1 >: TT} // just val vv: _ >: TT is illegal here: unbound wildcard type
}

trait P1 extends P {
  type TT <: Product
  val vv: Product
}

trait P2 extends P1 with P {
  type TT <: Tuple1[Int]
  val vv: Tuple1[Int]
}

由于TT1 forSome {type TT1 >: TT} =:= Any,它等于

// (*)

trait P {
  type TT
  val vv: Any
}

trait P1 extends P {
  type TT <: Product
  val vv: Product
}

trait P2 extends P1 with P {
  type TT <: Tuple1[Int]
  val vv: Tuple1[Int]
}

由于存在类型在Scala 3中被推荐为路径依赖类型,因此在Scala 3中可以被翻译为(*)或

trait P {
  type TT

  trait Inner {
    type TT1 >: TT
    val vv: TT1
  }

  val i: Inner
}

trait P1 extends P {
  type TT <: Product
}

trait P2 extends P1 with P {
  type TT <: Tuple1[Int]
}

相关问题