私は関数型プログラミング、特に関数型 Java で遊んでいます。私は自分のバージョンの IO Monad を成功裏に実装し、自分のコア用の IO アクションを書いています。基本的に、オブジェクトを Xml ファイルにシリアル化します (オブジェクト タイプは、カスタム XmlWritable インターフェイスを拡張します)。
残念ながら、これを行うには、OutputStream のインスタンスと XmlSerializer の 1 つのインスタンスを作成する必要があります。OutputStream のスコープは XmlSerializer のスコープよりも広いため、IO モナド内で両方のライフサイクルを正しく処理できることがわかる唯一の方法は、両方をタプルに入れ、XmlSerializer を使用して記述した後に OutputStream を閉じることです。 .
これは重くて醜いコードにつながります (Java 6 は間違いなくこれに最適ではありません):
public abstract class IO<R> {
[...]
}
public class IOActions {
public final F<String, IO<OutputStream>> openFileFn() {
return new F<String, IO<OutputStream>>() {
@Override
public IO<OutputStream> f(String fileName) {
[...]
}
};
}
/* This will be partially applied, encoding will be fixed */
public static final F<OutputStream, IO<P2<OutputStream, XmlSerializer>>> initSerializer() {
return new F<OutputStream, IO<P2<OutputStream, XmlSerializer>>>() {
@Override
public IO<P2<OutputStream, XmlSerializer>> f(OutputStream os) {
XmlSerializer = new ...
[...]
}
};
}
/* This will be partially applied as well */
public static final F2<XmlWritable, P2<OutputStream, XmlSerializer>, IO<P2<OutputStream, XmlSerializer>>> writeObjectFn() {
return new F2<XmlWritable, P2<OutputStream, XmlSerializer>, IO<P2<OutputStream, XmlSerializer>>>() {
@Override
public IO<P2<OutputStream, XmlSerializer>> f(XmlWritable object, P2<OutputStream, XmlSerializer> p) {
[...]
}
};
}
関数型プログラミングでユースケースを処理するより慣用的な理由はありますか?
潜んでいると、私は状態モナドを発見しました...しかし、Functional JavaでIOモナドの上に状態モナドを適用するとどうなるかを見るのがちょっと怖いです。