2014年3月21日金曜日

Java8でカリー化を書いてみた

部分適用を実装した前の投稿に続いて、Java8でカリー化を書いてみた。 前回書いた F2とF3に、2引数の関数の入れ子を返す curry() を追加した。こんな感じ。
package c2;
import java.util.function.Function;
import java.util.function.BiFunction;

interface F1<T, R> extends Function<T, R> {
}
interface F2<T, U, R> extends BiFunction<T, U, R> {
  default F1<U, R> apply(T p1) {
    return p2 -> apply(p1, p2);
  }
  default F1<T, F1<U, R>> curry() {
    return p1 -> p2 -> apply(p1, p2);
  }
}
interface F3<T, U, V, R> {
  R apply(T t, U u, V v);
  default F2<U, V, R> apply(T p1) {
    return (p2, p3) -> apply(p1, p2, p3);
  }
  default F1<T, F1<U, F1<V, R>>> curry() {
    return p1 -> p2 -> p3 -> apply(p1, p2, p3);
  }
}
public final class CurryTest {
  public static void main(final String[] args) {
    F3<Integer, String, Integer, Integer> f = 
      (n, s, i) -> String.format("%d%s", n, s).length() + i;
    F1<Integer, F1<String, F1<Integer, Integer>>> f3 = f.curry();

    F1<String, F1<Integer, Integer>> f2 = f3.apply(77);
    F1<Integer, Integer> f1 = f2.apply("ab");
    Integer rf = f1.apply(1230);

    System.out.println(rf);// 1234
    System.out.println(f.curry().apply(77).apply("ab").apply(1231));// 1235

    F2<String, Integer, Integer> g = f.apply(77);
    F1<String, F1<Integer, Integer>> g2 = g.curry();

    F1<Integer, Integer> g1 = g2.apply("ab");
    Integer rg = g1.apply(1232);

    System.out.println(rg);// 1236
    System.out.println(g.curry().apply("ab").apply(1233));// 1237
  }
}
特に難しいことはない。

前の投稿で、F1からF3まで実装して、F4以上も同じ要領と書いたが、いっそ F2 以上は全部カリー化された関数で表現するって手もある。もちろんトレードオフはいろいろあるだろうけど。

0 件のコメント:

コメントを投稿