LoginSignup
3
2

More than 5 years have passed since last update.

インナークラスのコンストラクタを外から無名クラスとして継承できるようになったeclipse

Posted at

ふと ECJ (eclipse compiler for Java) bug. インナークラスのコンストラクタを外から無名クラスとして継承すると型エラー のことを思い出した。
JavaコンパイラECJのインナークラスに関するバグを2件見つけて、パッチを送ったのだった。
現在のバージョンKepler Service Release 2 ではパッチが反映されていることを確認した。

これは、Java7以前でモナドをいかに軽量に書けるか?ということを試していて発見したのだった。

せっかくなので、全く意味のない例ではあるが、 これを使って State モナドを書いてみた。 ほげほげ.new Bind<..>(){...}.run() と書けるようになった、というところ(だけ)がポイントだ。

Java 7 ではこれが限界だけど、 Java 8 ではどれくらい軽量に書けるだろうか?

StateSample.java
package _sandbox;

import static _sandbox.State.*;

public class StateSample {
    public static void main(String args[]) {

        // in Haskell: snd . runState (get >>= \s -> put (s+1) >>= \_ -> get) 100

        Integer x = new Get<Integer>().new Bind<Unit>(){
            public State<Integer,Unit> f(Integer s) {
                return new Put<>(s+1);
            }
        }.new Bind<Integer>(){
            public State<Integer, Integer> f(Unit _) {
                return new Get<>();
            }
        }.run(100).snd;

        System.out.println(x); // 101
    }   
}
State.java
package _sandbox;

final class Pair<X,Y> {
    public final X fst;
    public final Y snd;
    public Pair(X fst, Y snd) {
        this.fst = fst;
        this.snd = snd;
    }
}

final class Unit{
    public static final Unit unit = new Unit();
    private Unit() {}
}

public abstract class State<S,A> {

    public abstract Pair<S,A> run(S s);

    // return
    public static final class Return<S,A> extends State<S,A> {
        public final A ret; 
        public Return(A ret) {
            this.ret = ret;
        }
        public final Pair<S,A> run(S s) {
            return new Pair<>(s,this.ret);
        }
    }

    // bind (>>=)
    public abstract class Bind<B> extends State<S,B> {
        public abstract State<S,B> f(A a); // override this
        public final Pair<S,B> run(S s) {
            Pair<S,A> result = State.this.run(s);
            return this.f(result.snd).run(result.fst);
        }
    }

    // get
    public static final class Get<S> extends State<S,S> {
        public Get() {}
        public final Pair<S,S> run(S s) {
            return new Pair<>(s,s);
        }
    }

    // put
    public static final class Put<S> extends State<S,Unit> {
        public final S newState;
        public Put(S newState) {
            this.newState = newState;
        }
        public final Pair<S,Unit> run(S _) {
            return new Pair<>(this.newState,Unit.unit);
        }
    }   
}
3
2
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
3
2