カリー化

複数の引数を取る関数を、1 つの引数を取る関数の連鎖に変換する手法

関数型プログラミングJavaScript

カリー化とは

カリー化 (Currying) は、複数の引数を取る関数 f(a, b, c) を、1 つの引数を取る関数の連鎖 f(a)(b)(c) に変換する手法である。Haskell Curry にちなんで名付けられた。部分適用と組み合わせて、関数の再利用性を高める。

基本

// 通常の関数
function add(a: number, b: number): number {
  return a + b;
}
add(1, 2); // 3

// カリー化
function curriedAdd(a: number) {
  return (b: number) => a + b;
}
curriedAdd(1)(2); // 3

// 部分適用: 引数を固定した新しい関数を作る
const add10 = curriedAdd(10);
add10(5);  // 15
add10(20); // 30

実用的な例

// ログレベルを固定したロガー
const createLogger = (level: string) => (message: string) =>
  console.log(`[${level}] ${message}`);

const info = createLogger('INFO');
const error = createLogger('ERROR');

info('Server started');   // [INFO] Server started
error('DB connection failed'); // [ERROR] DB connection failed
// API エンドポイントを固定した fetch
const createFetcher = (baseUrl: string) => (path: string) =>
  fetch(`${baseUrl}${path}`).then(r => r.json());

const api = createFetcher('https://api.example.com');
const users = await api('/users');
const orders = await api('/orders');

汎用的なカリー化関数

function curry<A, B, C>(fn: (a: A, b: B) => C): (a: A) => (b: B) => C {
  return (a: A) => (b: B) => fn(a, b);
}

const multiply = curry((a: number, b: number) => a * b);
const double = multiply(2);
double(5); // 10

カリー化 vs 部分適用

概念 説明
カリー化 f(a, b)f(a)(b) (全引数を 1 つずつ)
部分適用 f(a, b)g(b) (一部の引数を固定)

カリー化は部分適用を可能にする手法。

React での活用

// イベントハンドラの部分適用
function TodoList({ items, onDelete }: Props) {
  return (
    <ul>
      {items.map(item => (
        <li key={item.id}>
          {item.text}
          <button onClick={() => onDelete(item.id)}>Delete</button>
        </li>
      ))}
    </ul>
  );
}

使いすぎに注意

カリー化を多用するとコードが読みにくくなる。明確なメリット (部分適用による再利用) がある場合にのみ使う。

カリー化の背景や設計思想は関連書籍に詳しい。

関連用語