将数字加在一起

| 我有一个列表[Number]。它包含Number的不同子类的值-Int,Double等。我想将所有值加在一起。如果列表仅包含Int,则希望结果为Int。如果有混合,我想遵循正常的Scala规则:Int + Double = Double(依此类推)。 我已经试过了:
val result = list.reduceLeft(_ + _)
这甚至是不可编译的。 Number没有定义+接受另一个Number的方法。 我该怎么做? 安德烈斯     
已邀请:
        从最初提出问题的Scala邮件列表中复制我的答案:
Number
是Java类,除了将其自身转换为原始类型外,没有其他功能。不幸的是,Scala的
AnyVal
除了标记原始类型没有任何作用,而Scala的
Numeric[T]
只知道它自己的类型,而不是类型的混合。 因此,您将获得相当不愉快的模式匹配;如果您确定只需要处理double和int,则最短的语法为:
list.reduceLeft((l,r) => (l: Any, r: Any) match {
  case (li: Int, ri: Int) => li + ri
  case _ => l.doubleValue + r.doubleValue
})
请注意,我正在强制转换为
Any
以获得Scala模式匹配项来为我们进行拆箱;如果您将其保留为Number,则必须先在
java.lang.Integer
和pattern7ѭ上进行模式匹配,这很痛苦。 如果您想要更多,则必须进行适当的促销:
list.reduceLeft((l,r) => (l: Any) match {
  case li: Int => (r: Any) match {
    case ri: Int => li + ri
    case rf: Float => li + rf
    case rl: Long => li + rl
    case _ => li + r.doubleValue
  }
  case lf: Float => /* etc. */
})
如果您要做的不止一点,最好放弃9英镑,而转而使用您自己的包装类,这些包装类知道如何将自己添加到适当的提升中;那么您只需编写一次模式匹配,然后在列表推导中返回使用+。
sealed abstract class Addable {
  def +(a: Addable): Addable
}

final case class MyInt(value: Int) extends Addable {
  def +(a: Addable) = a match {
    case MyInt(i) => MyInt(value + i)
    case MyFloat(f) => MyFloat(value + f)
    ...
  }
}

final case class MyFloat(value: Float) extends Addable {
  def +(a: Addable) = a match {
    case MyInt(i) => MyFloat(value + i)
    ...
  }
}

...
这种方法的一个小优点是,您可以决定以不同于标准的方式提升价值(例如,您可能会决定float + long = double,因为实际上并没有切掉float来保留很多long \的数字精度,例如,ѭ11。 都比较尴尬; Java和Scala均未真正提供对混合类型数学的支持。     
        通过减少ѭ12的列表。 不要使用类
Number
,您实际上无法用它完成任何事情。它甚至不是Scala类,而是Java类。     

要回复问题请先登录注册