Ale*_*ack 7 generics numerical scala
在Scala中,我希望能够编写使用>,/,*等运算符的泛型类,但是我没有看到如何约束T这样才能使用.
我考虑使用Ordered [T]约束T,但这似乎不起作用,因为只有RichXXX(例如RichInt)扩展它,而不是Int等.我也看到了Numeric [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
}
}
Run Code Online (Sandbox Code Playgroud)
这个类不会编译,因为有很多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)
}
Run Code Online (Sandbox Code Playgroud)
如果我们改变原始类,可以在实例化时混合使用.
PS 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
}
Run Code Online (Sandbox Code Playgroud)
您可以使用" 查看边界".
简而言之,def foo[T <% U](t: T)
是一个函数将接受任何或者可以隐式转换为U的函数.由于Int可以转换为RichInt(包含您想要的方法),这是一个很好的使用示例.
class MaxOfList[T <% Ordered[T]](list: List[T] ) {
def max = {
val seed: Option[T] = None
list.foldLeft(seed)(getMax(_,_))
}
private def getMax(xOption: Option[T], y: T) = (xOption, y) match {
case (Some(x), y) if ( x > y ) => xOption
case (_, y) => Some(y)
}
}
Run Code Online (Sandbox Code Playgroud)
PS - 我重写了你的getMax(...)方法来比较值而不是选项本身,并使用模式匹配而不是isDefined(...)
PPS - Scala 2.8将具有可能有用的数字特征.http://article.gmane.org/gmane.comp.lang.scala/16608
附录
只是为了咯咯笑,这里的超紧凑版本完全消除了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)
}
}
Run Code Online (Sandbox Code Playgroud)
然而另一个附录
这个版本对于大型列表更有效...避免为每个元素创建一些(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))
}
}
Run Code Online (Sandbox Code Playgroud)
最后一个,我保证!
此时,您可以放弃该类并使用一个函数:
def max[T <% Ordered[T]](i: Iterable[T]) = {
if (i.isEmpty) None
else Some(i.reduceLeft((a,b) => if (a > b) a else b))
}
Run Code Online (Sandbox Code Playgroud)
归档时间: |
|
查看次数: |
1868 次 |
最近记录: |