scala:实现一个通用的递归 max 函数
声明:本页面是StackOverFlow热门问题的中英对照翻译,遵循CC BY-SA 4.0协议,如果您需要使用它,必须同样遵循CC BY-SA许可,注明原文地址和作者信息,同时你必须将它归于原作者(不是我):StackOverFlow
原文地址: http://stackoverflow.com/questions/12506791/
Warning: these are provided under cc-by-sa 4.0 license. You are free to use/share it, But you must attribute it to the original authors (not me):
StackOverFlow
scala: implement a generic recursive max function
提问by opensas
I'm trying to port this haskell max function implementation to scala
我正在尝试将此 haskell max 函数实现移植到 Scala
maximum' :: (Ord a) => [a] -> a
maximum' [] = error "maximum of empty list"
maximum' [x] = x
maximum' (x:xs) = max x (maximum' xs)
This is my first attempt:
这是我的第一次尝试:
def max[T <: Ordered[T]](list: List[T]): T = list match {
case Nil => throw new Error("maximum of empty list")
case head :: Nil => head
case list => {
val maxTail = max(list.tail)
if (list.head > maxTail) list.head else maxTail
}
}
max(List[Int](3,4))
But I get the following error:
但我收到以下错误:
inferred type arguments [Int] do not conform to method max's type parameter bounds [T <: Ordered[T]]
I tried with ordering, comprable, etc with similar results...
我尝试订购,可比较等,结果类似......
Any idea about what's missing?
知道缺少什么吗?
回答by dejon97
Went through a similar exercise as the OP sans pattern matching and generic types, and came up with the following:
经历了与 OP sans 模式匹配和泛型类型类似的练习,并得出以下结论:
def max(xs: List[Int]): Int = {
if (xs.isEmpty) throw new NoSuchElementException
if (xs.length == 1)
return xs.head
else
return max(xs.head, max(xs.tail))
}
def max(x: Int, y: Int): Int = if (x > y) x else y
回答by dhg
Maybe you want the Orderingtype class?
也许你想要Ordering类型类?
def max[T: Ordering](list: List[T]): T = list match {
case Nil => throw new RuntimeException("maximum of empty list")
case head :: Nil => head
case list =>
val maxTail = max(list.tail)
if (implicitly[Ordering[T]].gt(list.head, maxTail)) list.head else maxTail
}
This is, after all, how the built-in maxmethod works:
毕竟,这就是内置max方法的工作原理:
// From GenTraversableOnce
def max[A1 >: A](implicit ord: Ordering[A1]): A
You can clean things up a lot if you do this:
如果你这样做,你可以清理很多东西:
def max[T](list: List[T])(implicit ord: Ordering[T]): T = list match {
case Nil => throw new RuntimeException("maximum of empty list")
case head :: Nil => head
case head :: tail => ord.max(head, max(tail))
}
Or, you can make it tail-recursive for increased efficiency (because the compiler will optimize it):
或者,您可以将其设为尾递归以提高效率(因为编译器会对其进行优化):
def max[T](list: List[T])(implicit ord: Ordering[T]): T = {
if (list.isEmpty)
throw new RuntimeException("maximum of empty list")
@tailrec
def inner(list: List[T], currMax: T): T =
list match {
case Nil => currMax
case head :: tail => inner(tail, ord.max(head, currMax))
}
inner(list.tail, list.head)
}
Also, you should throw RuntimeExceptionor a subclass of it, not Error.
此外,您应该 throwRuntimeException或其子类,而不是Error.
回答by eomeroff
I have just come up with this solution.
我刚刚想出了这个解决方案。
def max(xs: List[Int]): Int = {
if (xs.isEmpty) 0
else {
if( xs.head >= max(xs.tail) ) xs.head
else max(xs.tail)
}
}
回答by Hegemon
I came up with quite a simple solution which is easy to understand. It caters for an empty list, a list with only one element, and negative numbers.
我想出了一个非常简单的解决方案,很容易理解。它适用于空列表、只有一个元素的列表和负数。
def max(xs: List[Int]): Int = {
if (xs.isEmpty) throw new NoSuchElementException
else {
def inner(max: Int, list: List[Int]): Int = {
def compare(x: Int, y: Int): Int =
if (x > y) x
else y
if (list.isEmpty) max
else inner(compare(max, list.head), list.tail)
}
inner(xs.head, xs.tail)
}
}
回答by opensas
Oops, shoulda look better before asking
哎呀,在问之前应该看起来更好
I found the answer in this thread: https://stackoverflow.com/a/691674/47633
我在这个线程中找到了答案:https: //stackoverflow.com/a/691674/47633
It seems like Haskell's type classes are implemented using implicits in scala (like in dhg's example)
似乎 Haskell 的类型类是使用 Scala 中的隐式实现的(如在 dhg 的示例中)
so it ends up like this:
所以它最终是这样的:
def max[T](list: List[T])(implicit f: T => Ordered[T]): T = {
def maxElement(value1: T, value2: T): T = if (value1 > value2) value1 else value2
list match {
case Nil => throw new Error("empty list found")
case head :: Nil => head
case list => maxElement(list.head, max(list.tail))
}
}
or with some syntactic sugar, just
或者用一些语法糖,只是
def max[T <% Ordered[T]](list: List[T]): T = list match {
Still, I think the compiler has enough information to do it by himself...
不过,我认为编译器有足够的信息可以自己完成......
ps: I prettied up a little bit the function...
ps:我美化了一点功能...
回答by flydes
def genFunc[A](a1: A, a2: A)(f:(A, A) => Boolean):A = if (f(a1, a2)) a1 else a2
def min[A : Ordering] = (a1: A, a2: A) => implicitly[Ordering[A]].lt(a1, a2)
def max[A : Ordering] = (a1: A, a2: A) => implicitly[Ordering[A]].gt(a1, a2)
List(1,2,8,3,4,6,0).reduce(genFunc(_,_)(min))
List(1,2,8,3,4,6,0).reduce(genFunc(_,_)(max))
or if need only function max with tail recursion and the type Option[_] does not break the referential transparency
或者如果只需要使用尾递归函数 max 并且类型 Option[_] 不会破坏引用透明度
def max[A: Ordering](list: List[A]): Option[A] = list match {
case Nil => None
case h :: Nil => Some(h)
case h :: t => if(implicitly[Ordering[A]].gt(h, t.head)) max(h :: t.tail) else max(t)
}
max(List(1,2,8,3,4,6,0)).getOrElse("List is empty") // 8: Any
max(List()).getOrElse("List is empty") // List is empty: Any
回答by Hind Ahmad
this is the simplest way I could come up with:
这是我能想到的最简单的方法:
def max(xs: List[Int]): Int = { if (xs.length == 1) xs.head
else if(xs.isEmpty) throw new NoSuchElementException
else if(xs.head > max(xs.tail)) xs.head
else max(xs.tail)} }
回答by Jay A
this works
这有效
def max(xs: List[Int]): Int = xs match{
case Nil => 0
case head :: Nil => head
case head :: tail => max(List(head, max(tail)))
}
回答by Buggi
My solve:
我的解决:
def max(xs: List[Int]): Int = {
if (xs.isEmpty) 0
else xs.max
}

