Generics Scala:在泛型类中执行数值运算的最佳方法是什么?

Generics Scala:在泛型类中执行数值运算的最佳方法是什么?,generics,scala,numerical,Generics,Scala,Numerical,在Scala中,我希望能够编写使用诸如>、/、*等运算符的泛型类,但我不知道如何约束t以使其工作 我研究了用有序[T]约束T,但这似乎不起作用,因为只有RichXXX(例如RichInt)扩展了它,而不是Int等。我还看到了数值[T],这只在Scala 2.8中可用吗 下面是一个具体的例子: class MaxOfList[T](list: List[T] ) { def max = { val seed: Option[T] = None list .map(

在Scala中,我希望能够编写使用诸如>、/、*等运算符的泛型类,但我不知道如何约束t以使其工作

我研究了用有序[T]约束T,但这似乎不起作用,因为只有RichXXX(例如RichInt)扩展了它,而不是Int等。我还看到了数值[T],这只在Scala 2.8中可用吗

下面是一个具体的例子:

class MaxOfList[T](list: List[T] ) {
  def max = {
    val seed: Option[T] = None

    list
      .map( t => Some(t))
      // Get the max      
      .foldLeft(seed)((i,m) => getMax(i,m) )
  }

  private def getMax(x: Option[T], y: Option[T]) = {
    if ( x.isDefined && y.isDefined )
      if ( x > y ) x else y
    else if ( x.isDefined )
      x
    else
      y
  }
}
这个类不会编译,因为有很多Ts不支持>等

想法

现在,我已经使用了一个MixIn特性来解决这个问题:

/** Defines a trait that can get the max of two generic values
 */
trait MaxFunction[T] {
  def getMax(x:T, y:T): T
}

/** An implementation of MaxFunction for Int
 */
trait IntMaxFunction extends MaxFunction[Int] {
  def getMax(x: Int, y: Int) = x.max(y)
} 

/** An implementation of MaxFunction for Double
 */
trait DoubleMaxFunction extends MaxFunction[Double] {
  def getMax(x: Double, y: Double) = x.max(y)
} 
如果我们改变原始类,可以在实例化时混合使用

p.S.Mitch,受您重新编写getMax的启发,这里是另一个:

  private def getMax(xOption: Option[T], yOption: Option[T]): Option[T] = (xOption,yOption) match {
    case (Some(x),Some(y)) => if ( x > y ) xOption else yOption
    case (Some(x), _) => xOption
    case _ => yOption
  }
你可以用

简而言之,
def foo[T xOption
案例(u,y)=>Some(y)
}
}
PS-我重写了getMax(…)方法来比较值而不是选项本身,并使用模式匹配而不是isDefined(…)

PPS-Scala2.8将有一个可能有用的数字特性


附录

这里是一个超级紧凑的版本,它完全消除了getMax方法:

class MaxOfList[T <% Ordered[T]](list: List[T] ) {
  def max = list.foldLeft(None: Option[T]) {
      case (Some(x), y) if ( x > y ) => Some(x)
      case (_, y) => Some(y)
  }
}
class MaxOfList[ty)=>Some(x)
案例(u,y)=>Some(y)
}
}

另一个附录

此版本对于大型列表更有效…避免为每个元素创建一些(x):

class MaxOfList[T <% Ordered[T]](list: List[T] ) {
  def max = {
    if (list.isEmpty) None
    else Some(list.reduceLeft((a,b) => if (a > b) a else b))
  }
}
class MaxOfList[T如果(a>b)a或者b))
}
}

最后一个,我保证!

此时,您可以放弃类并使用函数:

  def max[T <% Ordered[T]](i: Iterable[T]) = {
    if (i.isEmpty) None
    else Some(i.reduceLeft((a,b) => if (a > b) a else b))
  }
def max[T如果(a>b)a否则b))
}

与scala 2.8中的
数字[T]

scala> case class MaxOfList[T : Numeric](list: List[T]) {
     |     def max = if(list.isEmpty) None else Some(list.max)
     | }
defined class MaxOfList

scala> MaxOfList(1::2::3::9::7::Nil).max

res1: Option[Int] = Some(9)

scala> MaxOfList(1.5::3.9::9.2::4.5::Nil).max

res2: Option[Double] = Some(9.2)

scala> MaxOfList(Nil: List[Byte]).max

res3: Option[Byte] = None

scala>
正如所回答的,这就是视图边界的用途。现在,
Numeric
只是在Scala 2.8上添加的,而不是说它不依赖于Scala 2.8的任何功能。在Scala 2.7上也可以做同样的事情

您可能对我编写的一些通用代码片段感兴趣:


再次感谢米奇。我发誓我试过了,但没能编译出来!我用你的另一个版本的getMax对原始问题进行了更新。我用你的另一个版本更新了我的getMax。在我们达到某种奇点之前还有多少次迭代?嘿,我认为我们正在接近完美的我随着更改速度的减慢,实现速度似乎在减慢。问题:您的最新版本确实有效吗?如果我读对了,我认为getMax(Some(2),Some(3))将在返回3时返回2。也许第二种情况应该是case((Some(x)),None))=>?再次重写以消除列表上的映射。请注意,值的选项发生在折叠功能中。
scala> case class MaxOfList[T : Numeric](list: List[T]) {
     |     def max = if(list.isEmpty) None else Some(list.max)
     | }
defined class MaxOfList

scala> MaxOfList(1::2::3::9::7::Nil).max

res1: Option[Int] = Some(9)

scala> MaxOfList(1.5::3.9::9.2::4.5::Nil).max

res2: Option[Double] = Some(9.2)

scala> MaxOfList(Nil: List[Byte]).max

res3: Option[Byte] = None

scala>