【问题标题】:Having associated types in a Scala enumeration在 Scala 枚举中具有关联类型
【发布时间】:2020-08-26 09:33:12
【问题描述】:

我已经创建(我认为)一个具有关联类型的枚举,其约束条件是关联类型必须是 Numeric 特征的实现:

  sealed trait DataType[T <: Numeric[T]] { type NumT = T }
  trait Positions extends DataType[Double] 
  trait Values extends DataType[Double]
  trait Weights extends DataType[Double]
  trait Prices extends DataType[Double]

这看起来一切都很好,甚至可能很好,但是我想在案例类中使用这个枚举,而不必复制类型参数 - 所以下面这个非工作示例的精神代码:

  case class SingleValue[DataT <: DataType] (
    datum: DataT#NumT,
  ) {
    def addToDatum(plus: DataT#NumT): SingleValue[DataT] = (this.datum += plus)
  }

这不能编译,我也不能让它工作 - 编译器要求 DataType 上的类型参数,但即使给定一个 - 像

  case class SingleValue[T <: Numeric[T], DataT <: DataType[T]]

我仍然遇到问题,在这种情况下,我在重复自己,无论如何,枚举的优势大部分都消失了。

谁能引导我走上正确的道路?

谢谢!

【问题讨论】:

  • 这段代码中没有枚举,所以不清楚你的意思。
  • @jwvh 我的理解是,使用带有多个扩展的密封特征是在 Scala 中进行枚举的惯用方式。
  • 你得到的是Algebraic Data Type。更具体地说,它是一个总和类型的 ADT。惯用枚举从扩展 Enumeration class 开始。

标签: scala generics enums


【解决方案1】:

只需从DataType 中删除类型参数即可。

sealed trait DataType {
  type NumT <: Numeric[NumT]
}
trait Positions extends DataType {
  type NumT = Double
}

但请注意,这不会编译,原因与您的原始代码无法编译的原因相同:Double 不是Numeric[Double] 的子类型。

不过,您可以使用不同的 DataType 定义:

sealed trait DataType {
  type NumT
  implicit def numeric: Numeric[NumT]
}

【讨论】:

  • 感谢您。我可能很密集,但是如果我将您的第二个代码块用于 DataType 特征,我会收到一个错误:value += is not a member of DataT#NumT Expression does not convert to assignement because receiver not assignable。我是否还需要更改案例类本身?
  • += 不起作用,因为 datum 是在没有 var 关键字的情况下声明的,因此是不可变的。您还需要以某种方式访问​​数字实例,目前这是不可能的,因为您无权访问 SingleValue 中的任何 DataType 实例。但我认为,如果我们要进行有益的讨论,我们需要更多地讨论你在这里实际想要实现的目标,而不是机制。
  • 我基本上只是想在实例化这个案例类时为其指定一个(数字)类型。我正在使用枚举(或不使用枚举,请参阅上面来自@jwvh 的 cmets),因为我有一个 API 用户应该从一开始就定义的潜在类型列表。也许枚举是这里最简单的方法。我可能已经被这个奇怪的系统冲昏了头脑。
猜你喜欢
  • 1970-01-01
  • 1970-01-01
  • 2018-01-31
  • 1970-01-01
  • 1970-01-01
  • 2020-05-24
  • 1970-01-01
  • 1970-01-01
  • 2022-01-23
相关资源
最近更新 更多