5

モナドの一般的なケースはJava 6で表現できますか? 「一般的なケース」という言葉に注意してください — モナドの多くの特定のケース (つまり、多くの特定のモナド) は表現可能ですが、モナドの一般的なケースは表現できない可能性があります。

ここでの問題は、Java の高次ジェネリクス(の欠如)です。しかし、Haskell のサンプル コードは実際にはhttps://stackoverflow.com/a/877036/1123502 (つまりpublic class Fix<F extends Fix<F>>) のようなアプローチを使用して Java に移植されていることがわかりました。

もちろん、タイプ セーフでない実装 (オブジェクトやダウンキャストの使用など) は興味深いものではありません。

更新: 2 つの一般的なモナド定義があります: join-fmap と bind-return です。それらは (数学的に) 同等ですが、一方の定義は Java で表現可能であり、他方はそうではないという意味では同等ではない可能性があります (ただし、非同等である可能性は低いと思われます)。したがって、私の質問は両方の定義に関するものです。

結論: Java 6 ですべての障害を克服し、「一般的なケース」のモナドを書いた人はいますか? または、別の方法として、論文や詳細なブログ投稿を指摘するか、それが不可能な理由を詳細に説明してください。

4

1 に答える 1

5

汚いキャスティングトリックがないわけではありません。すでに指摘したように、Java は型レベルのポリモーフィズム (別名、Scala ランドの「より高い種類の型」) をサポートしていません。

1 つの方法を次に示します。ファンクタを実装するとします。Functor<F<A>>、どこにFaListやなどを書きたいのですがMaybe、うまくいきません。Base<X,Y>しかし、より高度なもののための「基本クラス」を持つことができます。Xのような実際のクラスの「証人」でなければなりませんListY通常のジェネリック パラメータです。これでファンクターは になりますがFunctor<Base<F,A>>、これで使用したいすべてのクラスは を実装する必要がありますBase<X,Y>:

class List<A> implements Base<List.Witness,A> {
   public class Witness{}
   ...
}

public interface Functor<F> {
    public <A, B> Base<F, B> map(F1<A, B> fn, Base<F, A> nestedA);
}

public class ListFunctor implements Functor<List.Witness> {
    public <A, B> Base<List.Witness, B> map(F1<A, B> fn, Base<List.Witness, A> nestedA) {
       ...
    }  
}

もちろん、支払うべき代償は、Base<List.Witness,B>ではなくを返すことですList<B>。高次のドメインにとどまっている場合はこれで問題ないかもしれません。もちろん、便利な変換関数を使用することもできますが、それでもあまり良くありません。

実装については、私のそれほど深刻ではないプロジェクトhighJを参照してください。上記の例に近い、完全に書き直された、わずかに便利なバージョンに取り組んでいることに注意してください。

真面目なコードの場合は、そのようなものを代わりに Scala で書くことを検討してください (または Scalaz を使用してください)。

于 2012-11-25T17:38:33.917 に答える