LoginSignup
15
17

More than 5 years have passed since last update.

[Java] カリー化と部分適用

Last updated at Posted at 2015-11-02

カリー化

カリー化を調べると、以下のように書いてあります。

カリー化 (currying, カリー化された=curried) とは、複数の引数をとる関数を、引数が「もとの関数の最初の引数」で戻り値が「もとの関数の残りの引数を取り結果を返す関数」であるような関数にすること(あるいはその関数のこと)である。
(中略)
カリー化は部分適用と混同されやすい[1][2]。

wikipedia:カリー化

つまり、以下の3つの概念(というのかな?)があるわけですよね。

  • 部分適用
  • 普通の関数をカリー化したもの
  • 最初からカリー化された関数として作られたもの

準備

ためしに作ってみた。

こんなインタフェースがあるとして…。

import java.util.function.BiFunction;
import java.util.function.Function;

interface F1<T, R> extends Function<T, R> {
    default R x(T t) {
        return apply(t);
    }
}

interface F2<T, U, R> extends BiFunction<T, U, R> {
    /** 部分適用 */
    default F1<U, R> x(T p1) {
        return p2 -> apply(p1, p2);
    }

    /** カーリー化 */
    default F1<T, F1<U, R>> currying() {
        return p1 -> p2 -> apply(p1, p2);
    }
}

interface F3<T, U, V, R> {

    R apply(T t, U u, V v);

    /** 部分適用 (1項目) */
    default F2<U, V, R> x(T p1) {
        return (p2, p3) -> apply(p1, p2, p3);
    }

    /** 部分適用 (2項目) */
    default F1<V, R> x(T p1, U p2) {
        return p3 -> apply(p1, p2, p3);
    }

    /** カーリー化 */
    default F1<T, F1<U, F1<V, R>>> currying() {
        return p1 -> p2 -> p3 -> apply(p1, p2, p3);
    }
}

そして、適当な「普通の関数」があるとします。

        // 0. 引数が3つの関数を作る
        F3<String, String, String, String> f = (s, e, v) -> s + v + e;

部分適用

部分適用とは、以下の 1-1. のような感じ。

        // 1-1. 部分適用する
        F1<String, String> partialFunction = f.x("[", "]");

        // 1-2. 部分適用した関数を使う
        String value1 = partialFunction.x("xyz");
        System.out.println(value1); // "[xyz]"

普通の関数をカリー化

普通の関数をカリー化するというのは、以下の 2-1. のような感じ。

        // 2-1. 普通の関数をカリー化する
        F1<String, F1<String, F1<String, String>>> curried = f.currying();

        // 2-2. カリー化した関数に部分適用する
        F1<String, String> sandwich1 = curried.x("{").x("}");
        // 2-3. 部分適用した関数をさらに使う
        String value2 = sandwich1.x("abc");
        System.out.println(value2); // "{abc}"

最初からカリー化されている関数

最初からカリー化されている関数を作るのは、以下の 3-1. のような感じ。

        // 3-1. 最初からカリー化されている関数を作る
        F1<String, F1<String, F1<String, String>>> g = s -> e -> v -> s + v + e;

        // 3-2. カリー化されている関数を使う
        String value3 = g.x("(").x(")").x("123");
        System.out.println(value3); // "(123)"
15
17
0

Register as a new user and use Qiita more conveniently

  1. You get articles that match your needs
  2. You can efficiently read back useful information
  3. You can use dark theme
What you can do with signing up
15
17