ジャバおじさんが Elm のカスタム型を理解しようと思って Java で考えたメモです。
チョクワガタとかは詳しくないです。
カスタム型の例として Result
を取り上げます:
ElmのResult定義
type Result error value
= Ok value
| Err error
上記の Result
を Java で表現した一例:
Result.java
interface Result {
class Ok<V> implements Result {
final V value;
Ok(V value) { this.value = value; }
}
class Err<E> implements Result {
final E error;
Err(E error) { this.error = error; }
}
}
- アクセス修飾子周りはサボりました。
- Java でカスタム型を 再現 することが目的ではないのであんまり頑張ってません。
- ホントはちょっと頑張った (
Result
にE
とV
を持たせたり) けど色々面倒くさかったのでやめました。
- ホントはちょっと頑張った (
Java版 Result
型を実際に使った例:
Main.java
class Main {
public static void main(String[] args) {
show(validate("100")); // -> Ok: 100
show(validate("200hoge")); // -> Err: 数値を入力してください
}
/**
* text が数字のみから構成されている文字列か検証する。
* @param text 検証対象の文字列。
* @return text が数字のみから構成されている場合、Integer.parseInt(text) の結果を
* value フィールドにセットした Result.Ok 。<br>
* text に数字以外が含まれている場合、"数値を入力してください" を
* error フィールドにセットした Result.Err 。
*/
static Result validate(String text) { // 「基礎からわかるElm」P.91 の validate 関数が元ネタ
try {
var n = Integer.parseInt(text);
return new Result.Ok<>(n);
} catch (NumberFormatException e) {
return new Result.Err<>("数値を入力してください");
}
}
/**
* result の内容を標準出力に出力する。
* @param result 出力する値。
*/
static void show(Result result) {
if (result instanceof Result.Ok) {
var ok = (Result.Ok<Integer>) result;
System.out.println("Ok: " + ok.value);
} else if (result instanceof Result.Err) {
var err = (Result.Err<String>) result;
System.out.println("Err: " + err.error);
} else {
throw new RuntimeException("謎の型が指定されています");
}
}
}
型パラメータに指定している Integer
や String
への依存がひどかったり insutanceof
で分岐してたりとカッコつかないコードですね。
頑張らなかったのでしょうがない。 こんなん雰囲気でええんや。
Elm のカスタム型は Java で考えるとこんな感じになるかなーというのが今の認識です。
本来は代数的データ型をちゃんと学ぶべきですが、とりあえず理解は進んだ (気がする) のでヨシ!としてます。