10

この haskell max 関数の実装を scala に移植しようとしています

maximum' :: (Ord a) => [a] -> a  
maximum' [] = error "maximum of empty list"  
maximum' [x] = x  
maximum' (x:xs) = max x (maximum' xs) 

これは私の最初の試みです:

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))

しかし、次のエラーが表示されます。

inferred type arguments [Int] do not conform to method max's type parameter bounds [T <: Ordered[T]]

同様の結果で、順序付け、比較可能などで試しました...

何が欠けているかについて何か考えはありますか?

4

9 に答える 9

21

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
于 2014-04-26T18:34:05.533 に答える
18

多分あなたは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
}

結局のところ、これは組み込みmaxメソッドがどのように機能するかです。

// From GenTraversableOnce
def max[A1 >: A](implicit ord: Ordering[A1]): A

これを行うと、多くのものをきれいにすることができます:

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))
}

または、効率を高めるために末尾再帰にすることもできます (コンパイラが最適化するため)。

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)
}

RuntimeExceptionまた、ではなく、そのサブクラスをスローする必要がありErrorます。

于 2012-09-20T05:58:11.953 に答える
6

私はちょうどこの解決策を思いつきました。

def max(xs: List[Int]): Int = {
    if (xs.isEmpty) 0
    else {
      if( xs.head >= max(xs.tail) ) xs.head
      else max(xs.tail)
    }
}
于 2013-03-30T00:10:26.473 に答える
2

理解しやすい非常にシンプルなソリューションを思いつきました。空のリスト、要素が 1 つしかないリスト、および負の数に対応します。

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)
  } 
}
于 2013-11-07T14:00:14.117 に答える
0

おっと、質問する前にもっとよく見てください

このスレッドで答えを見つけました: https://stackoverflow.com/a/691674/47633

Haskell の型クラスは scala で暗黙を使用して実装されているようです (dhg の例のように)

したがって、次のようになります。

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))
  }
} 

または、いくつかの構文シュガーを使用して、単に

def max[T <% Ordered[T]](list: List[T]): T = list match {

それでも、コンパイラは自分でそれを行うのに十分な情報を持っていると思います...

ps: 関数を少しきれいにしました...

于 2012-09-20T06:04:54.170 に答える