2 つの引数を持つ次の関数 f が与えられた場合、map を x のみに適用する標準的な方法は何ですか?
カリー化と部分適用に関するちょっとした議論
FP 用語では、関数f
は「カリー化されていません」です。概念的には 2 つの引数を取りますが、それらは単一の製品構造にバンドルされています。Python では、常にすべてがカリー化されていません。一度にすべての引数を指定するか、まったく指定しない必要があります。
これを回避するには、さまざまなトリックがありますが、概念的には関数を「カリー化」したいだけです。つまり、変換f(x,y)
先f(x)
は新しい関数を返しますg(y)
。
デフォルトでカリー化されている言語では、この翻訳を次のように簡単に書くことができます。
-- curry: take a function from (x,y) to one from x to a function from y to z
curry :: ((x,y) -> z) -> (x -> y -> z)
curry f x y = f (x, y)
したがってcurry
、カリーf
化された引数とその積の引数を別々に取り、それらがすべて利用可能になったら引数を適用します。反対も非常に簡単です。
uncurry :: (x -> y -> z) -> ((x,y) -> z)
uncurry f (x,y) = f x y
これは部分適用とどのように関係していますか?
- カリー化は、1 つの構造体( n -product) 引数を取る関数を取り、 n 個の引数を取る新しい関数を返します。
- 部分適用は、n 個の引数の関数を取り、それらをk 個の引数に適用して、残りの引数がnk個の関数を生成します。
アンカリー化言語では、各引数を順番に適用できます (たとえば、関数のアリティに関して部分的に)。カリー化された言語では、上記の例のように、最初に関数をアンカリー化するためにいくつかのトリックを実行する必要があります。
部分的な適用は無料なので、デフォルトでカリー化された環境にいる方が柔軟だと思います。このような環境では、データ構造をパイプラインに変更する関数をチェーン化するのが一般的です。たとえば、整数変更のパイプライン:
(+1) . (*2) . (^3) $ 7
部分的に適用され、カリー化されていない関数のチェーンであり、構成され、それぞれが前の関数の出力を操作します。懸念事項を視覚的に分離するので、これは便利です。