Skip to content

Instantly share code, notes, and snippets.

Show Gist options
  • Save asufana/851eae50f9ad2084a2b3771675b46d81 to your computer and use it in GitHub Desktop.
Save asufana/851eae50f9ad2084a2b3771675b46d81 to your computer and use it in GitHub Desktop.
「代数的データ型で状態を記述する」のJava検討

「代数的データ型で状態を記述する」の Java 検討

OCaml でのサンプル

参考:イベント・ドリブンプログラムの関数型的書き方

代数的データ型で状態を定義

直和型(列挙型にフィールドを付加したもの)を利用することで、複数の直積型を定義する。

type button = Bar | Line | Scatter
type state =
    OverWrite of button list
  | Normal of button

ボタンを一般化した状態遷移

let on_button_click b = function
    | OverWrite bs when List.exists((=) b) bs -> OverWrite (List.filter((<>) b) bs)
    | OverWrite bs -> OverWrite (b::bs)
    | Normal _ -> Normal b

Java で書き換えてみる

  • Java には列挙型(Enum)があるが、直和型はないため、
  • Enum とフィールドを合わせ持つ ValueObject Group 的なクラス ButtonsState で表現する
//ボタン状態を管理するVOGroup
public static class ButtonsState {
    public final State state;
    public final Selected selected;
    
    //ファクトリ
    public ButtonsState newState(final Button button) {
        if (state.equals(State.OverWirte)) {
            if (selected.contains(button)) {
                return new ButtonsState(this.state, this.selected.remove(button));
            }
            else {
                return new ButtonsState(this.state, this.selected.add(button));
            }
        }
        return new ButtonsState(this.state, new Selected(button));
    }
    
    //ファクトリ
    public ButtonsState newState(final State state) {
        return new ButtonsState(state, this.selected);
    }
    
    //コンストラクタ
    ButtonsState(final State state, final Selected selected) {
        this.state = state;
        this.selected = selected;
    }
    
    //重ね描画種別
    public static enum State { OverWirte, Normarl; }
    
    //ボタン種別
    public static enum Button { Bar, Line, Scatter; }
    
    //選択されているボタン群を表現するVO
    public static class Selected {
        public final List<Button> buttons;
        
        //コンストラクタ
        public Selected(final Button button) {
            this(Arrays.asList(button));
        }
        
        //コンストラクタ
        public Selected(final List<Button> buttons) {
            this.buttons = Collections.unmodifiableList(buttons);
        }
        
        public boolean contains(final Button button) {
            return buttons.contains(button);
        }
        
        public Selected remove(final Button button) {
            final List<Button> newList = new ArrayList<>(buttons);
            newList.remove(button);
            return new Selected(buttons);
        }
        
        public Selected add(final Button button) {
            final List<Button> newList = new ArrayList<>(buttons);
            newList.add(button);
            return new Selected(buttons);
        }
    }
}

うーん、さすがJava。コードが長い。。

Sign up for free to join this conversation on GitHub. Already have an account? Sign in to comment