関数型プログラミング

カリー化 かりーか

関数型プログラミング部分適用ラムダ式クロージャ高階関数JavaScript
カリー化について教えて

簡単に言うとこんな感じ!

「複数の引数をまとめて受け取る関数」を「引数を1個ずつ受け取る関数の連鎖」に変換する技術だよ!カレーの「カリー」じゃなくて、数学者のハスケル・カリーさんの名前からきてるんだ。料理で言えば「まとめて注文」を「1品ずつ注文」に変えるイメージ!


カリー化とは

カリー化(Currying)とは、複数の引数を受け取る関数を、「1つの引数を受け取って関数を返す関数」の連鎖に変換する手法です。たとえば add(1, 2) のように2つの引数を同時に渡す関数を、add(1)(2) のように1つずつ渡せる形に変えることを指します。

名前の由来は、数学者・論理学者のハスケル・カリー(Haskell Curry)です。彼はこの概念を体系化した人物として知られており、関数型プログラミング言語「Haskell」もその名を冠しています。カリー化によって関数を部分適用(引数を一部だけ渡して新しい関数を作る)できるようになり、コードの再利用性が大きく高まります。

ビジネスパーソンの感覚で言えば「ひな型づくり」に近いです。「税率8%で計算する関数」「税率10%で計算する関数」を個別に作る代わりに、「税率を受け取って計算関数を返す関数」を1つ用意しておけば、あとは税率を差し込むだけで使い回せます。コードの重複を減らし、保守性を高める実務的な技術です。


カリー化の仕組み

カリー化の前後でどう変わるか、JavaScriptを例に見てみましょう。

カリー化「前」と「後」の比較

項目通常の関数カリー化後の関数
呼び出し方add(1, 2)add(1)(2)
引数の渡し方まとめて渡す1つずつ渡す
途中で止められる?❌ できない✅ できる(部分適用)
再利用しやすい?
// ── 通常の関数 ──────────────────────────────
function add(x, y) {
  return x + y;
}
add(1, 2); // 3

// ── カリー化した関数 ─────────────────────────
function curriedAdd(x) {
  return function(y) {
    return x + y;
  };
}
curriedAdd(1)(2); // 3

// ── 部分適用の活用例 ─────────────────────────
const add10 = curriedAdd(10); // 「10を足す関数」を生成
add10(5);  // 15
add10(20); // 30
[通常の関数]           [カリー化後]
 add(x, y)              add(x)
     │                    │
     ▼                    ▼
   結果                 fn(y)


                        結果

覚え方:「1つ渡すと、次の関数が返ってくる」

🍛 カリー化 = カレーのルーを1枚ずつ溶かすイメージ 一度に全部入れるのではなく、1枚ずつ溶かして次のステップへ進む。 「1引数 → 関数 → 1引数 → 関数 → … → 結果」という流れを思い浮かべよう。

カリー化と部分適用の違い

よく混同される「部分適用(Partial Application)」との違いも押さえておきましょう。

用語意味
カリー化関数を「1引数→関数」の連鎖に変換する変換操作f(a,b,c)f(a)(b)(c)
部分適用引数の一部を先に渡して新しい関数を作る操作f(a,b,c)a だけ渡して g(b,c) を作る

カリー化は「変換の仕組み」、部分適用は「その仕組みを使った活用法」と理解すると整理しやすいです。


歴史と背景

  • 1930年代 — 数学者ハスケル・カリー(Haskell Curry)とモーゼス・シェーンフィンケル(Moses Schönfinkel)が、多引数関数を1引数関数の連鎖で表現できることを数学的に示す。厳密にはシェーンフィンケルが先に発見したが、カリーの名が定着した
  • 1958年 — LISPが登場し、関数を値として扱う「第一級関数」の概念がプログラミングの世界に持ち込まれる
  • 1970年代 — MLやHaskellの前身となる関数型言語の研究が進み、カリー化が言語の基本機能として組み込まれ始める
  • 1990年 — 関数型言語Haskellが登場。Haskellではすべての関数がデフォルトでカリー化されており、カリー化が言語設計の中心概念に
  • 2000年代〜 — JavaScriptの普及とともに関数型プログラミングのスタイルが注目され、lodash/fpRamda などのライブラリがカリー化ユーティリティを提供
  • 2010年代〜TypeScriptScalaKotlinSwiftなどのモダン言語でも関数型スタイルが一般化し、カリー化はフロントエンド・バックエンド問わず広く使われる技術になる

言語ごとのカリー化の扱い方

言語によってカリー化の扱いは大きく異なります。「最初からカリー化されている言語」と「自分でカリー化を実装する言語」に分かれます。

デフォルトでカリー化済み Haskell 全関数が自動的にカリー化される F# ML系。標準で部分適用が使える Elm フロント向け関数型言語。自動カリー化 OCaml 学術・産業両用。デフォルトカリー化 ライブラリ・手動で実現 JavaScript / TypeScript Ramda / lodash/fp で実現 Python functools.partial で部分適用が可能 Scala _ で部分適用、curry メソッドで変換 Kotlin / Swift ラムダ・クロージャで手動実装 カリー化の対応スタイル比較

実務でよく見るパターン(JavaScript × Ramda)

import * as R from 'ramda';

// Ramda の curry を使ったカリー化
const multiply = R.curry((x, y) => x * y);

const double  = multiply(2);  // 「2倍にする関数」を生成
const triple  = multiply(3);  // 「3倍にする関数」を生成

double(5);  // 10
triple(5);  // 15

// パイプラインとの組み合わせ(実務的な使い方)
const process = R.pipe(
  R.filter(x => x > 0),  // 正の数だけ残す
  R.map(double),          // 2倍にする
  R.reduce(R.add, 0)      // 合計する
);

process([-1, 2, 3, -4, 5]); // (2+3+5)×2 = 20

関連する規格・RFC

※ カリー化はプログラミングの数学的概念であり、特定のIETF RFC・ISO・IEEE規格は存在しないため、このセクションは省略します。


関連用語

  • 高階関数 — 関数を引数や戻り値として扱う関数。カリー化された関数の基盤となる概念
  • クロージャ — 外側のスコープ変数を「閉じ込める」関数。カリー化の実装に欠かせない仕組み
  • ラムダ式 — 名前を持たない無名関数。カリー化と組み合わせてよく使われる
  • 関数型プログラミング — カリー化が中心概念として位置づけられるプログラミングパラダイム
  • 部分適用 — 引数を一部だけ渡して新しい関数を生成する操作。カリー化と密接に関連
  • イミュータブル — 関数型プログラミングのもう一つの柱。状態を変更しない設計思想
  • パイプライン — 関数を連鎖させてデータを変換する手法。カリー化との組み合わせで真価を発揮