web-dev-qa-db-ja.com

foldとfoldLeftまたはfoldRightの違いは?

注:Scala 2.8—それが問題になりますか?

foldまたはfoldLeftと同じ方法でfoldRight関数を使用できないのはなぜですか?

Set scaladoc には次のように書かれています:

折りたたみの結果は、この並列コレクションの型パラメーターTのスーパータイプのみになります。

しかし、関数シグネチャに型パラメーターTはありません。

def fold [A1 >: A] (z: A1)(op: (A1, A1) ⇒ A1): A1

foldLeft-Rightfoldの違いは何ですか。後者をどのように使用しますか?

編集:たとえば、リスト内のすべての要素を追加するために折り畳みをどのように作成しますか? foldLeftの場合:

val foo = List(1, 2, 3)
foo.foldLeft(0)(_ + _)

// now try fold:
foo.fold(0)(_ + _)
>:7: error: value fold is not a member of List[Int]
  foo.fold(0)(_ + _)
    ^
63
Andriy Drozdyuk

古いバージョンのScala=が問題です。 scaladocページ for Scala= 2.8。 1、そこに定義された折り畳みは表示されません(これはエラーメッセージと一致します)明らかに、foldはScala 2.9。

8
exlevan

短い答え:

foldRightは右側に関連付けられます。つまり要素は右から左の順に蓄積されます。

List(a,b,c).foldRight(z)(f) = f(a, f(b, f(c, z)))

foldLeftは左に関連付けられます。つまりアキュムレータが初期化され、要素が左から右の順にアキュムレータに追加されます。

List(a,b,c).foldLeft(z)(f) = f(f(f(z, a), b), c)

foldassociativeです。要素が一緒に追加される順序は定義されていません。つまりfoldの引数は、モノイドを形成します。

68
Apocalisp

foldは、foldRightおよびfoldLeftとは異なり、コレクションの要素が処理される順序に関する保証を提供しません。おそらく、処理が保証されていない並列コレクションで、より制約の多いシグネチャを持つfoldを使用することをお勧めします。処理順序が保証されていないため、並列コレクションは並列にフォールディングを実装できます。署名を変更する理由は似ています。制約が追加されているため、平行折りを行うのが簡単です。

54

他の答えに同意します。簡単な説明例を与えると考えました:

 object MyClass {
 def main(args: Array[String]) {
val numbers = List(5, 4, 8, 6, 2)
 val a =  numbers.fold(0) { (z, i) =>
 {
     println("fold val1 " + z +" val2 " + i)
  z + i

 }
}
println(a)
 val b =  numbers.foldLeft(0) { (z, i) =>
 println("foldleft val1 " + z +" val2 " + i)
  z + i

}
println(b)
   val c =  numbers.foldRight(0) { (z, i) =>
   println("fold right val1 " + z +" val2 " + i)
  z + i

}
println(c)
 }
}

結果は自明です:

fold val1 0 val2 5
fold val1 5 val2 4
fold val1 9 val2 8
fold val1 17 val2 6
fold val1 23 val2 2
25
foldleft val1 0 val2 5
foldleft val1 5 val2 4
foldleft val1 9 val2 8
foldleft val1 17 val2 6
foldleft val1 23 val2 2
25
fold right val1 2 val2 0
fold right val1 6 val2 2
fold right val1 8 val2 8
fold right val1 4 val2 16
fold right val1 5 val2 20
25
3
Ram Ghadiyaram

特定の例では、foldLeftと同じ方法でコーディングします。

val ns = List(1, 2, 3, 4)
val s0 = ns.foldLeft (0) (_+_) //10
val s1 = ns.fold (0) (_+_) //10
assert(s0 == s1)
3
Garrett Rowe