generic の自己再帰定義活用
Haskell の Monad の bind は、戻り値が第一引数と同じ Monadインスタンスでないとなりません。そうでないとモナド則が成り立たないですしね。
そもそも Haskell の ad-hoc polymorphism では、同じ型クラスの違うインスタンスを混ぜて扱うことは許していないようです。その辺、Java や C# などの polymorphism とは違うところなので混乱しやすいかもしれませんね。
さて、では Java の interface で、Haskell のように、戻り値を実装クラス形に限定するようなメソッドを定義できるでしょうか?
完璧には行かないまでも自己再帰定義によって実現することができます。
public interface Function<ARG, RET> { RET call(ARG argument); } public interface Monad<T, K extends Monad<T, K>> { K bind(Function<? super T, ? extends K> func); } public class Maybe<T> implements Monad<T, Maybe<T>> { @Override public Maybe<T> bind(Function<? super T, ? extends Maybe<T>> func) { return isNothing() ? this : func.call(value); } // isNothing() とか諸々省略 }
ちょっと型パラメータの定義がごちゃごちゃしすぎて、ぱっと見では意図が取りづらいですね。
それでもやりたかった事はおおよそできています。実装クラスで型パラメータ K を自クラスではなく別の実装クラスで指定できてしまうので、完璧とは言いがたいですが。