カリー化は複数の引数を取る関数を、1 つの引数を取る関数のチェーンに変換する手法です。部分適用と組み合わせることで柔軟な関数合成が可能になります。
カリー化とは
# 通常の関数 def add(a, b, c): return a + b + c add(1, 2, 3) # 6 # カリー化された関数 def add_curried(a): def f(b): def g(c): return a + b + c return g return f add_curried(1)(2)(3) # 6
汎用的なカリー化関数
from functools import wraps import inspect def curry(func): @wraps(func) def curried(*args, **kwargs): sig = inspect.signature(func) try: sig.bind(*args, **kwargs) return func(*args, **kwargs) except TypeError: return lambda *more_args, **more_kwargs: curried( *args, *more_args, **{**kwargs, **more_kwargs} ) return curried @curry def add(a, b, c): return a + b + c print(add(1)(2)(3)) # 6 print(add(1, 2)(3)) # 6 print(add(1)(2, 3)) # 6
実用例:設定の部分適用
@curry def format_message(template, name, value): return template.format(name=name, value=value) # テンプレートを固定 greeting = format_message("Hello, {name}! Your score is {value}.") print(greeting("Alice")(100)) # Hello, Alice! Your score is 100.
部分適用との違い
カリー化
複数引数関数を 1 引数関数のチェーンに変換。f(a, b, c) → f(a)(b)(c)
部分適用
一部の引数を固定した新しい関数を作る。f(a, _, c) → g(b)
functools.partial との組み合わせ
from functools import partial @curry def power(base, exponent, modulo=None): if modulo: return pow(base, exponent, modulo) return base ** exponent square = power(exponent=2) # カリー化で base を待つ print(square(5)) # 25
カリー化は関数型プログラミングの基盤であり、ポイントフリースタイルや関数合成と相性が良いです。