在Haskell中,我编写了一个函数,给定List of a
,返回Maybe a
。
max' :: Ord a => [a] -> Maybe a
max' [] = Nothing
max' (x:xs) = Just $ foldr (\y acc -> if (y > acc) then y else acc) x xs
我怎么能在Scala中写这个?我不确定Scala中的Ord
等价物。
答案 0 :(得分:8)
您可以使用scalaz.Order
或scala.math.Ordering
:
使用Scalaz:
def max[A](as: List[A])(implicit ord: Order[A]): Option[A] =
as.foldLeft(None: Option[A]) {
case (None, a) => Some(a)
case (s @ Some(m), a) => if (ord.greaterThanOrEqual(m, a)) s else Some(a)
}
不
def max[A](as: List[A])(implicit ord: math.Ordering[A]): Option[A] =
as.foldLeft(None: Option[A]) {
case (None, a) => Some(a)
case (s @ Some(m), a) => if (ord.gteq(m, a)) s else Some(a)
}
请注意,Scalaz为所有def maximum: Option[A]
个实例定义Foldable
:
scala> import scalaz.syntax.foldable._
import scalaz.syntax.foldable._
scala> import scalaz.std.AllInstances._
import scalaz.std.AllInstances._
scala> List(1, 2, 3).maximum
res0: Option[Int] = Some(3)
标准库为所有集合定义def max: A
,但它不安全:
scala> (Nil: List[Int]).max
java.lang.UnsupportedOperationException: empty.max
...
答案 1 :(得分:3)
直接翻译你的Haskell版本:
scala> def max[a](vs: List[a])(implicit ord: math.Ordering[a]): Option[a] = vs match {
| case Nil => None
| case x::xs => Some(xs.foldLeft(x)(ord.max))
| }
max: [a](vs: List[a])(implicit ord: scala.math.Ordering[a])Option[a]
scala> max(1::2::3::4::2::Nil)
res0: Option[Int] = Some(4)
scala> max[Int](Nil)
res1: Option[Int] = None
scala> max("abcdefg".toList)
res2: Option[Char] = Some(g)
或更可能的版本:
scala> def max[a <% math.Ordered[a]](vs: List[a]): Option[a] = vs match {
| case Nil => None
| case x::xs => Some(xs.foldRight(x){ (v, r) => if(v > r) v else r })
| }
max: [a](vs: List[a])(implicit evidence$1: a => scala.math.Ordered[a])Option[a]
scala> max(1.0::2.3::4.5::1.6::Nil)
res4: Option[Double] = Some(4.5)