使用未签名和签名的整数设计编号系统

Chr*_*art 10 scala

我正在尝试围绕无符号整数和有符号整数设计编号系统.这两种类型都有一个underlying值,表示Scala数字系统中的数字.这是我到目前为止的类型层次结构.

sealed trait Number {
  def + (num : Number) : Number = ???
  def - (num : Number) : Number = ???
  def * (num : Number) : Number = ???
}

sealed trait SignedNumber extends Number

sealed trait UnsignedNumber extends Number

sealed trait UInt32 extends UnsignedNumber {
  def underlying : Long
}

sealed trait UInt64 extends UnsignedNumber {
  def underlying : BigInt
}

sealed trait Int32 extends SignedNumber {
  def underlying : Int
}

sealed trait Int64 extends SignedNumber {
  def underlying : Long
}
Run Code Online (Sandbox Code Playgroud)

我想underlying在特征中定义,Number以便编译器可以强制执行underlying在所有子节点中定义的.但是,underlying每种特性的类型各不相同 - 我希望为每种类型保留尽可能小的类型.例如,a UInt32可以存储为longScala中,而a UInt64需要存储为BigInt.

这样做最有效的方法是什么?

Chr*_*tin 3

type您可以在父特征中声明 a并在子特征中覆盖它。

sealed trait Number {
  type A
  def underlying: A
  def + (num : Number) : Number = ???
  def - (num : Number) : Number = ???
  def * (num : Number) : Number = ???
}

sealed trait SignedNumber extends Number

sealed trait UnsignedNumber extends Number

sealed trait UInt32 extends UnsignedNumber {
  override type A = Long
}

sealed trait UInt64 extends UnsignedNumber {
  override type A = BigInt
}

sealed trait Int32 extends SignedNumber {
  override type A = Int
}

sealed trait Int64 extends SignedNumber {
  override type A = Long
}
Run Code Online (Sandbox Code Playgroud)

一个示例只是为了在不清楚的情况下展示路径相关类型的使用:

def getUnderlying(x: Number): x.A = x.underlying
Run Code Online (Sandbox Code Playgroud)

为了获得正确的返回类型,我认为type可能需要另一个。

sealed trait Number {
  type A
  type B
  def underlying: A
  def +(that: B): B
}

sealed trait UInt32 extends Number { x =>
  override type A = Long
  override type B = UInt32
  override def +(y: B): B = new UInt32 {
    // todo - naive implementation, doesn't check overflow
    override val underlying = x.underlying + y.underlying
  }
}

def main(args: Array[String]) {
  print((
    new UInt32 { def underlying = 3 } +
    new UInt32 { def underlying = 4 }
  ).underlying)
}
Run Code Online (Sandbox Code Playgroud)