以下の内容はhttps://m-hiyama.hatenablog.com/entry/20060412/1144801562より取得しました。


Javaで高階プログラミング、ってそれ何よ!

昨日の「プログラマのための述語論理」で、暗黙的に“総称的な高階関数”が出現してしまいました。それで今日は、意図的に「Javaで高階関数を扱えるだろうか? 」とやってみました。結論を先に言えば、ちょっとシンドい

関数オブジェクト

まずは、関数オブジェクトを次のインターフェースで定義します。

public interface Function<X, Y> {
 Y apply(X x);
}

Functionをimplementsするクラスのインスタンスは、型がX→Yの関数です(そう思いこむことにする)。f(x) の代わりに f.apply(x) と書く必要がありますが、我慢しましょう。

2引数関数はというと、次のインターフェースを使う手があります。

public interface FunctionOfArity2<X1, X2, Y> {
 Y apply(X1 x1, X2 x2);
}

が、今回はペア(長さ2のタプル)を使いましょう。

public class Pair<X1, X2> {
 private X1 _1;
 private X2 _2;
 public Pair(X1 x1, X2 x2) {
  _1 = x1;
  _2 = x2;
 }
 public X1 first() {return _1;}
 public X2 second() {return _2;}
}

(X1, X2→Y)という型の関数は、Function<Pair<X1, X2>, Y>型だとみなします。

実例:足し算関数

毎度お馴染みの足し算する関数を定義して実行してみます。

public class Sum {
 public static void main(String[] args) {
  Function<Pair<Integer, Integer>, Integer> sum =
     new Function<Pair<Integer, Integer>, Integer>() {
       public Integer apply(Pair<Integer, Integer> arg) {
        return arg.first() + arg.second(); // ここが本体
       }
     };
  // y = 5 + 3;
  int y = sum.apply(new Pair<Integer, Integer>(5, 3));
  System.out.println("y = " + y);
 }
}
C:\tmp>java Sum
y = 8

それでカリー化

これまたお決まりのカリー化、いってみよう。(JavaScriptのカリー化、「ハラワタを取り出して改変してからもう一度突っこむ」というブラックジャック式にえぐい/ださい方法が→http://d.hatena.ne.jp/m-hiyama/20051213/1134446855にあります。)

public class Curry<X, Y, Z> implements 
  Function<Function<Pair<X, Y>, Z>, Function<X, Function<Y, Z>>>
{
 public Function<X, Function<Y, Z>>
 apply(final Function<Pair<X, Y>, Z> func) 
 {
  return new Function<X, Function<Y, Z>>() {
    public Function<Y, Z> apply(final X x) {
     return new Function<Y, Z>() {
       public Z apply(Y y) {
        return func.apply(new Pair<X, Y>(x, y));
       }
     };
    }
  };
 }
}

ウニョニョ、なんじゃこりゃー。ほんとにカリー化になっているの?

public class CurrySample {
 public static void main(String[] args) {
  // 最初の例
  // curry(sum)(5)(3) = 8
  Function<Pair<Integer, Integer>, Integer> sum =
     new Function<Pair<Integer, Integer>, Integer>() {
       public Integer apply(Pair<Integer, Integer> arg) {
        return arg.first() + arg.second();
       }
     };

  Curry<Integer, Integer, Integer> int_int_int_curry = 
     new Curry<Integer, Integer, Integer>();
  Function<Integer, Integer> sum5 = 
     (int_int_int_curry.apply(sum)).apply(5);
  int y = sum5.apply(3);
  System.out.println("y = " + y); // y = 5 + 3 = 8

  // もうひとつの例
  // curry(repeat)("Hi")(4) = "HiHiHiHi"
  Function<Pair<String, Integer>, String> repeat =
     new Function<Pair<String, Integer>, String>() {
       public String apply(Pair<String, Integer> arg) {
        String s = "";
        String x = arg.first();
        for (int i = 0; i < arg.second(); i++) {
          s = s + x;
        }
        return s;
       }
     };

  Curry<String, Integer, String> str_int_str_curry = 
     new Curry<String, Integer, String>();
  Function<Integer, String> repeatHi = 
     (str_int_str_curry.apply(repeat)).apply("Hi");
  System.out.println(repeatHi.apply(4)); // HiHiHiHi
 }
}
C:\tmp>java CurrySample
y = 8
HiHiHiHi

なっ、なってるみたいです。

それがどうした

別にどうもしません。やってみただけ。特にお勧めはしません。




以上の内容はhttps://m-hiyama.hatenablog.com/entry/20060412/1144801562より取得しました。
このページはhttp://font.textar.tv/のウェブフォントを使用してます

不具合報告/要望等はこちらへお願いします。
モバイルやる夫Viewer Ver0.14