「Foldl」と「Foldr」の違い

2026/10/01 13:58

「Foldl」と「Foldr」の違い

RSS: https://news.ycombinator.com/rss

要約▶

Japanese Translation:

foldl
と
foldr
の主要な違いは、プログラミング言語が厳密評価(strict)か遅延評価(lazy)を行うかに依存します。厳密な言語では、
foldl
はテイル再帰を用いて定数のメモリ空間を使用しますが、
foldr
は長さ n のリストに対して線形スタック枠を必要とします。Haskell などの遅延言語において、標準的な
foldl
は大きなネストされたスंक(thunk)を作成し、線形空間を消費してしまいます。これは明示的に最適化されたプリムド版である
foldl'
を用いない限りです。
foldl'
はスünkを順次強制することで定数空間の動作を維持します。逆に、
foldr
は deferred evaluation(遅延評価)を自然に処理します。結合関数が厳密な場合は通常通り評価が進みますが、関数が遅延している場合(例えば
(:)
を使用する)、弱頭正常形(weak-head normal form)の結果をすぐに返し、無限リストを部分的に走査したり、結果のリストが完全に消費されていない場合に作業を節約できます。遅延言語における一般的なルールは、蓄積関数が厳密な場合は
foldl'
を使用し、蓄積関数の第二引数が遅延している場合は
foldr
を使用することです。標準的な
foldl
や
foldr'
(注:原文の記述に不一致があるため文脈より
foldr
と解釈)をリストに対して使用することは避け、そのプリムド版と比べて非最適化となります。厳密な Map.delete 操作には
foldl'
を使用してください。これらのフォールディングの違いはリストにのみ適用され、連結性が重要な木などの他のデータ構造については
foldMap
および
foldMap'
の使用が推奨されます(
foldMap'
は base-4.13.0.0 で追加され、GHC 8.8.1 を必要とします)。これらの慣行に従うことで、任意サイズのデータストリームを処理する際のメモリの安全性と高パフォーマンスが確保されます。(2026 年 9 月 25 日に Alexis King により公開された本稿は、2019 年 9 月 26 日付の hasura/graphql-engine!2933 の元の作品の再掲載です。)

本文

foldl と foldr の本質的な違い:厳密・非厳密評価の観点から

Alexis King による深層考察。Haskell の

foldl
と
foldr
は名前通り「左から」「右から」という探索順序の違いではなく、結合子(operator)の適用順序(結合性) に起因する違いです。本稿では、厳密な言語と非厳密な言語(遅延評価型言語)におけるそれぞれの挙動と最適化戦略を解説します。

1. 概念的な違い:結合性の理解

foldl
と
foldr
は、リストの要素を処理する順序(左から右へ)は同じですが、演算子(⨂)の括弧付きグループ化 が異なります。

計算式の比較

-- foldl の計算式:左結合 (Left Associative)
foldl (⨂) v [e0, e1, e2, ..., en]
-- ↓展開後
( ... (((v ⨂ e0) ⨂ e1) ⨂ e2) ... ) ⨂ en

-- foldr の計算式:右結合 (Right Associative)
foldr (⨂) v [e0, e1, e2, ..., en]
-- ↓展開後
e0 ⨂ (e1 ⨂ (e2 ⨂ ... (en ⨂ v)))

厳密な言語における挙動

厳密な言語では「内側から外へ」評価されます。

foldl
の例:

foldl (+) 0 [1, 2, 3, 4]
= (((0 + 1) + 2) + 3) + 4
-- 計算順序
(( (0+1)+2 ) + 3) + 4 
→ (( 3    +2 ) + 3) + 4 
→ (   5          + 3) + 4 
→      8                + 4 
→         10
  • 特性: 定数空間(Constant Space)で処理可能。尾再帰的(Tail Recursive)。
  • 要件: リストの先頭の要素のみがあれば計算開始可能。

foldr
の例:

foldr (+) 0 [1, 2, 3, 4]
= 1 + (2 + (3 + (4 + 0)))
-- 計算順序(右から内側へ)
1 + (2 + (3 +      4 )) 
→ 1 + (2 +           7)  
→ 1 +                9    
→                  10     
  • 特性: スタック深度 $N$ に比例した記憶領域を消費する(再帰的な性質のため)。

注意:

foldl
が「左から探索」と言われるのは誤解ではなく、結果が得られる準備としてリスト全体を読み込む必要があるためです。一方、
foldr
は「右から結合」するため、末尾要素を深くネストした形で保持する必要があります。


2. 非厳密な言語(Haskell など)における
foldl
の問題点

非厳密な言語では、評価順序が「外側から内側へ」になります。式は展開されず、計算結果が求められた瞬間までThunk(遅延評価された表現) として保持されます。

foldl
が生成する Thunk ツリー

-- foldl の展開
foldl (+) 0 [1, 2, 3, 4]
-- ↓厳密な言語なら
(((0 + 1) + 2) + 3) + 4

-- 非厳密な言語では(Thunk は ⟨ ⟩ で表記)
⟨⟨⟨⟨0 + 1⟩ + 2⟩ + 3⟩ + 4⟩

メリット・デメリット

  • メリット: 結果が要求されるまで計算を保留できる。
  • デメリット:
    • 入力リストのサイズに比例した巨大な Thunk ツリーが構築される。
    • リストをストリームとして処理する際、メモリ使用量が定数ではなく線形になる(空間効率の低下)。
    • 定数空間アルゴリズムが実質的に線形空間アルゴリズムに堕してしまうリスクがある。

解決策:
foldl'
の使用

巨大な Thunk を構築せず、各ステップで評価を強制的に行うための

foldl'
(Strict Fold Left)が必要です。

動作原理:

-- foldl' は直前の結果を計算してから次の処理へ進む
⟨0 + 1⟩ -- (ここで評価が強制される) → 1
→ 1 + 2  -- (次に評価) → 3
→ ...
  • 効果: 定数空間内で効率的にリストを消費し、不要な巨大な Thunk を回避できます。

3. 非厳密な言語における
foldr
の強み

非厳密な言語において、

foldr
はリストの末尾要素を即座に評価する必要がありません。これにより、部分計算(Partial Evaluation) とストリーミング処理が可能です。

結合子による挙動の違い

厳密な演算の場合(例:
+
)

foldr (+) 0 [1, 2, 3, 4]
= 1 + ⟨foldr (+) 0 [2, 3, 4]⟩ -- 未評価の Thunk が残る

結果が要求されるまで

+
の計算は完了せず、スタック状に蓄積されます。

非厳密な演算の場合(例:リスト構築
(:)
)

foldr (:) [] [1, 2, 3, 4]
= 1 : ⟨foldr (:) [] [2, 3, 4]⟩
-- ↓この時点で Weak Head Normal Form (WHNF) になり、評価停止
[1, 2, 3, 4] -- (リストとしての構造は即時に構築される)
  • (:)
    は左演算子(Cons)であり、先頭要素と尾部の Thunk を保持するだけで済むため、即座に結果として認識されます。

無限リストへの適用

この特性により、

foldr
は無限リストに対して機能します。一方、
foldl
や
foldl'
はリストの末尾まで評価するため、無限リストでは永続的に停滞(ループ)してしまいます。

部分リストの利用例

-- foldr を使うことで、必要な要素のみを処理できます
sum (take 2 (foldr f [] [1, 2, 3, 4])) 
where 
    f x xs = (x * 2) : xs -- 非厳密な累積関数
  • 上記では
    take 2
    で先頭 2 つ要素だけを取得するため、残りの
    foldr
    の呼び出し(
    [3, 4]
    など)は決して評価されません。計算リソースが節約されます。

4. まとめ:データ構造と累積関数による選択ガイド

foldl
と
foldr
を使い分けるための原則は、「累積関数の厳密性」 と**「必要な結果の量」** にあります。

基本的な経験則

  1. 累積関数が厳密な場合(例:合計、最小値など)

    • 推奨:
      foldl'
      を使用。
    • 理由: リスト全体を探索するため、定数空間で処理する必要がある。非厳密な
      foldl
      はメモリ効率が悪すぎる。
  2. 累積関数が第二引数(尾部)に対して非厳密な場合(例:リスト構築、無限リスト処理)

    • 推奨:
      foldr
      を使用。
    • 理由: 結果を即時に要求できず、ストリーミング処理や部分計算が可能なため。
  3. 常に避けるべき組み合わせ

    • ❌
      foldl
      (非厳密な関数でリスト全体を探索する場合):巨大な Thunk を生成する。
    • ❌
      foldr'
      (存在しないが、冗長な概念):通常不要。

具体的なコード例

厳密な処理が必要な場合(Map.Delete など)

-- Map.delete は厳密な関数(結果を確定させる必要があるため)
-- よって foldl' を使用すべき
let result = foldl' (\m k -> m `delete` k) map [x1, x2, x3]

※ リストサイズが小さければ微調整レベルですが、習慣として

foldl'
が推奨されます。

部分処理が必要な場合

-- 必要なリストの先頭のみを取得する場合
take 5 (foldr (\x acc -> x : acc) [] [1..]) -- 無限リストも扱える

補足:他のデータ構造について

  • Snoc リスト:
    foldl
    と
    foldr
    の役割が逆転します(右結合性が左側にあり)。
  • ツリーなどの木構造: 明確な左右の区別がないため、通常は
    FoldMap
    や
    FoldMap'
    を使用するのがベストプラクティスです。

結論: 適切なデータ構造と累積関数を選ぶことで、パフォーマンスと可読性を両立させられます。

同じ日のほかのニュース

一覧に戻る →

2026/10/06 4:16

Beam:反射の 501B オープンウェイトモデル

## Japanese Translation: 要約は主なナラティブを十分に捉えていますが、この文脈においてモデルの重要性を規定するハードウェア規模およびデータカurationに関するいくつかの定量的詳細が含まれていません。改良版は、具体的なGPU数、トレーニング環境の性質(サンドボックス)、明示的なデータフィルタリング統計を統合し、それがなぜ効率的かつ強力なのかというより完全な図像を提供する必要があります。 以下に、欠落している要素を取り入れながら流れを維持した改善された要約を示します: **改良された要約:** Reflection は、高効率なコーディング、複雑な推論、自律エージェントタスク向けに設計された最初のオープンウェイトスパースミキサー-of-エキスパート(MoE)モデル「Beam」を発表しました。全パラメータ数は Massive な 5010 億ですが、トークンあたり有効なのは 230 億のみであり、Beam は推論コストを劇的に削減しつつ、競合他社である GLM 5.2 と同等かそれ以上の性能を示し、特定のエージェントベンチマークでは Qwen 3.8-Max に迫ります。この効率性は、厳格な事前トレーニング(生データの約 95% が選別された 238 兆トークン)、ならびに 13 億個のサンドボックスを使用した 1 万台超の NVIDIA GB300 GPU クラスタ上で実施した先進的な強化学習によって実現されています。モデルは印象的な汎化性能を示し、ウェブブラウジングなどのツール使用スキルを明示的なトレーニングなしで習得します。来月後期に Apache 2.0 ライセンスの下で公開予定(早期アクセスはウェイトリスト経由)であり、「Reasoning Effort」パラメータを搭載して応答長とタスク複雑性のバランスを最適化しています。特に、トレーニング中での拡張により有効コンテキストを 100 万トークンまで引き上げられ、オープンウェイトモデルの効率性における重要なマイルストーンとなっています。

2026/10/06 6:00

Opus 5.5 エージェントが室温で機能する磁性半導体の候補物質 2 つを発見

## Japanese Translation: 研究者らは、反強磁性とスピンソート機能を統合する有望なルティンガー補償磁性体の候補を 2 つ同定した。これらは外部磁場なしで高密度メモリに既に利用可能な次世代スピントロニクス材料の存在を示唆している。候補 1 の YBaMnFeO₅ は AI エージェントによって設計されたものであり、イットリウム、バリウム、マンガン、鉄、酸素の 5 つの元素からなる化合物である。予測されるバンドギャップは 2.35 eV、正孔のスピンウィンドウは 1.0 eV、電子のスピンウィンドウは 1.4 eV であった。シミュレーションでは磁性が約 490 K に及ぶと予測されるが、原子チェッカーボード構造が高熱合成(900–1300 °C)において不安定化しうるため、特別な手法なしでこの温度域での標準的な高温合成を困難にしている。候補 2 の KV[Cr(CN)₆] は、1999 年に最初に見出されたプルussian ブルー族に属する既存化合物であり、半導体としてのスピン特性が以前見過ごされていた。クロムはシアン化物基(炭素で終端しており、バナジウムは窒素で終端する)に結合している。予測されるバンドギャップは 2.1 eV、正孔のスピンウィンドウは 2.6 eV、電子のスピンウィンドウは 1.6 eV であった。完全な結晶ではゼロの全スピンモーメントを持つと予測されるが、1999 年の粉体試料は閉じ込められた水の影響により約 365 K まで磁気秩序を保持しつつも、わずかな残留モーメント(0.125 ボアマグネトン)を示した。密度汎関数理論を用いた量子力学シミュレーションにより、両材料のこれらの特性が確認された。今後の研究では、KV[Cr(CN)₆] の純度を向上させて水起因のアーティファクトを排除し、YBaMnFeO₅ の脆い格子構造を安定化させる合成戦略の改善に焦点を当て、実用的かつ効率的な磁気メモリソリューションへの明確な経路を提供する。

2026/10/06 6:15

Dust:バックプロパゲーションなしでトランスフォーマーを事前学習する手法

## Japanese Translation: Dust は、Transformer リンゲージモデルの事前学習において逆伝播と競合するゼロ次最適化手法です。重みそのものを更新する代わりに、Dust はすべてのトークンごとに活性化空間への擾乱を適用し、「仮想集団」を生成します。これにより、単一の順方向パス内で数千の仮想モデルを並列評価でき、モデル重みの複雑な変化を実体化する必要がありません。EGGROLL-Transformer といった基準手法と比較して、100 万トークンのトークン予算以上においては、1,000 倍から 10,000 倍の効率向上を実現します。従来の常識とは対照的に、大規模モデル(最大 2.43 億パラメータ)は小規模モデルよりも集団効率が良く、2.43 億パラメータを持つモデルは、多くの集団サイズにおいて 120 倍小さいモデルを上回ります。Dust の勾配推定値は逆伝播と良好に一致し、集団サイズが増加するにつれて改善され、10 億トークンに至るまで強い一貫性を保ちます。この手法は、順方向パス間でレイヤ種をジッターさせ、また出力勾配の推定値を用いて直接のトークン損失ではなく注意内部をスコアリングすることで、擾乱間の相互干渉を低減します。ノイズスケールやクレジット減衰などの超パラメータは、学習なしで逆伝播勾配への余弦類似度を最大化するようにグリッド検索によってチューニング可能であり、トークン予算と集団サイズを跨いで汎化します。10 万から 2,000 万トークン、集団サイズ 64 から 1.6 万にわたる実験において、Dust は大規模のトークン予算下で集団サイズが増加するに伴い逆伝播とのギャップを縮めていることが示されています。Adam オプティマイザ(すべての手法向けに再チューニング)を用いても Dust は有効であり、低数のトークンでは理論的な限界が逆伝播を下回るものの、規模が大きくなるにつれて競合可能な性能を発揮します。大規模モデルは、より大きな探索空間とより良好な条件の損失地形幾何学により、集団サイズの増加からより多くの恩恵を受けます。Dust の推定値と逆伝播勾配の間の余弦類似度は、低 RMSE(< 0.06)で複数のレイヤ種に適合するべき乗律に従います。これらの進展は、高度な事前学習技術をよりアクセスしやすくし、専門的な訓練手順を必要としないまま大規模 AI 開発の民主化を促進します。

「Foldl」と「Foldr」の違い | そっか~ニュース