1

这是我的问题的最小再现:

  trait Superclass[T]
  
  class A(val key: Any) extends Superclass[key.type]
  
  val x: Superclass["123"] = A("123")

如您所见,我正在尝试将 Key 的静态已知类型编码到类型参数中。这不像我可以将类型key作为 A 的类型参数,因为在我的真实示例中,它更像,class A(using g: blablah)(val key: g.Key) extends SuperClass[g.Mapping[key.type]]但这与上述问题无关。

只是我们不能在超类的参数中使用依赖类型吗?

更新

类型成员的编码产生相同的错误:

  trait Superclass {
    type T
  }
  
  class A(val key: Any) extends Superclass {
    type T = key.type
  }
  
  val x: Superclass & {type T = "123"} = A("123")

我仍然得到

[error] 14 |  val x: Superclass & {type T = "123"} = A("123")
[error]    |                                         ^^^^^^^^
[error]    |                Found:    Main.A
[error]    |                Required: Main.Superclass & Object{T = ("123" : String)}
4

1 回答 1

1

我无法解决您给定的示例,但这可能适用于您的实际用例。

trait Superclass[T]

//The type of G
trait Foo:
  type Key
  type Mapping[K <: Key]

class A [K, KT <: K, M[_ <: K], G <: Foo {type Key = K; type Mapping[T <: K] = M[T]}] private(val key: KT, g: G)
    extends Superclass[M[KT]]

object A:
  def apply[G <: Foo](using g: G)(key: g.Key) =
     new A[g.Key, key.type, g.Mapping, g.type](key, g)

你可以像这样使用它:

class FooImpl extends Foo:
  type Key = String
  type Mapping[S <: String] = List[S]

given myG as FooImpl = FooImpl()

val x: Superclass[List["123"]] = A[FooImpl]("123")

Foo中,Key用于绑定可以给什么键MappingKclassA上的参数是key类型的上限,KT而是键的实际类型。M代表Mapping。我使用了类型细化,因为类型投影不可靠并且在 Scala 3 中已被删除。

为方便起见,您可以将apply方法添加到A'companion 并将A' 自己的构造函数设为私有。

看到它在Scastie中运行。

至于构造函数中的依赖类型,请参见这个问题。看起来您不能像在方法中那样使用它们。

于 2020-12-16T16:42:56.223 回答