Java 范围管理-有状态IO Monad?
我在玩函数式编程,尤其是函数式Java。我已经成功地实现了我的IO Monad版本,我正在为我的核心编写IO操作。它基本上是将对象序列化为Xml文件(对象类型扩展了自定义XmlWritable接口) 不幸的是,为了做到这一点,需要创建OutputStream的一个实例和XmlSerializer的一个实例。OutputStream的范围比XmlSerializer的范围更广,这意味着我能看到的正确处理IO monad中的两个生命周期的唯一方法是将它们一起放在元组中,在使用XmlSerializer编写之后关闭OutputStream 这导致了繁重而难看的代码(Java 6肯定不是最好的):Java 范围管理-有状态IO Monad?,java,functional-programming,functional-java,Java,Functional Programming,Functional Java,我在玩函数式编程,尤其是函数式Java。我已经成功地实现了我的IO Monad版本,我正在为我的核心编写IO操作。它基本上是将对象序列化为Xml文件(对象类型扩展了自定义XmlWritable接口) 不幸的是,为了做到这一点,需要创建OutputStream的一个实例和XmlSerializer的一个实例。OutputStream的范围比XmlSerializer的范围更广,这意味着我能看到的正确处理IO monad中的两个生命周期的唯一方法是将它们一起放在元组中,在使用XmlSerialize
公共抽象类IO{
[...]
}
公共集体诉讼{
公开最终文件F openFileFn(){
返回新的F(){
@凌驾
公共IO f(字符串文件名){
[...]
}
};
}
/*这将部分应用,编码将是固定的*/
公共静态final init序列化程序(){
返回新的F(){
@凌驾
公共IO f(输出流os){
XmlSerializer=新建。。。
[...]
}
};
}
/*这也将部分适用*/
公共静态最终F2 writeObject fn(){
返回新的F2(){
@凌驾
公共IO f(XmlWritable对象,p2p){
[...]
}
};
}
在函数式编程中,为什么要处理我的用例,还有更为惯用的说法吗
潜伏着,我发现了状态Monad…但我有点害怕看到如果我在Functional Java中的IO Monad之上应用状态Monad会发生什么。我实际上从Functional Java中获得了很大的灵感来解决类似的问题。我制作了自己的“XML组合器”(以及更多)从这个模式,所以它值得学习 你可能会发现谷歌群组很有用 编辑-回复评论: 按照代码进行操作:
请注意如何使用启动新连接,请注意,您有几个选项来启动连接,一个最终提交,另一个最终回滚。这只是两个可以在计算中“携带”的示例。本质上,您的每一次计算(普通的modaic绑定)都可能携带信息 以下是我在上述讨论中给出的一个示例:
DB<PreparedStatement> prepareStatement(final String sql) {
return new DB<PreparedStatement>() {
public PreparedStatement run(Connection c) throws SQLException {
return c.prepareStatement(sql);
}}}
// for a query that a reader might perform, i might have a function like this:
F<PreparedStatement, DB<ResultSet>> runStatement() {
public DB<ResultSet> f(final PreparedStatement s) {
return new DB<ResultSet>() {
public ResultSet run (Connection c) throws SQLException {
return s.executeQuery();
}}}
希望这有帮助!以下是我的想法。非常感谢您的反馈。 我遵循上面的答案,从讨论中获得灵感:
public class IOXml<T extends XmlWritable> implements DataWriter<T>{
private final XmlSerializer mXmlSerializer;
private final Option<String> mXmlEncoding;
private final IO<OutputStream> ioCreateStream;
private final F<OutputStream, IO<Unit>> ioCloseStream;
@Inject
IOXml(IO<OutputStream> createStream, F<OutputStream, IO<Unit>> closeStream, XmlSerializer xmlSerializer, Option<String> xmlEncoding) {
mXmlSerializer = xmlSerializer;
mXmlEncoding = xmlEncoding;
ioCreateStream = createStream;
ioCloseStream = closeStream;
}
/**
* Write a T object which is XmlWritable.
* @param osAndSer The tuple containing OutputStream and XmlSerializer.
* @param object The object to write.
* @return IO monad object.
*/
protected IO<Unit> writeObject(final T object) {
return new IO<Unit>() {
@Override
public Unit performIO() throws IOException {
object.writeXml(mXmlSerializer);
return Unit.unit();
}
};
}
protected final F<Unit, IO<Unit>> writeObjectFn(final T object) {
return new F<Unit, IO<Unit>>() {
@Override
public IO<Unit> f(Unit a) {
return writeObject(object);
}
};
}
/**
* Initialize the XmlSerializer before using it.
* @param os An OutputStream.
* @param encoding The encoding of the xml file.
* @return An IO action returning nothing.
*/
protected IO<Unit> initXml(final OutputStream os) {
return new IO<Unit>() {
@Override
public Unit performIO() throws IOException {
mXmlSerializer.setOutput(os, mXmlEncoding.toNull());
mXmlSerializer.startDocument(mXmlEncoding.toNull(), true);
return Unit.unit();
}
};
}
/**
* Close the XmlSerializer after.
* @return An IO action returning nothing.
*/
protected IO<Unit> closeXml() {
return new IO<Unit>() {
@Override
public Unit performIO() throws IOException {
mXmlSerializer.endDocument();
return Unit.unit();
}
};
}
protected final F<Unit, IO<Unit>> closeXmlFn() {
return new F<Unit, IO<Unit>>() {
@Override
public IO<Unit> f(Unit a) {
return closeXml();
}
};
}
@Override
public void close() throws IOException {
closeXml().performIO();
}
@Override
public void write(T object) {
throw new UnsupportedOperationException("Are you sure? IOXml is a functional class. Use the function returned by liftIO instead.");
}
/**
* Curried function to write XML objects, given the object itself and an OutputStream.
* @return The curried function.
*/
protected F<OutputStream, F<T, IO<Unit>>> writeFn() {
// returning the outer
return new F<OutputStream, F<T, IO<Unit>>>() {
@Override
public F<T, IO<Unit>> f(final OutputStream os) {
// Returning the inner
return new F<T, IO<Unit>>() {
@Override
public IO<Unit> f(T object) {
return initXml(os).bind(writeObjectFn(object)).bind(closeXmlFn());
}
};
}
};
}
@Override
public IO<Unit> writeIO(final T object) {
return IOImpl.bracket(ioCreateStream, // init
ioCloseStream, // close
Function.partialApply2(writeFn(), object)); // body
}
}
public类IOXml实现DataWriter{
私有最终XmlSerializer mXmlSerializer;
私人最终选择权MXMLENCODE;
私有最终IO ioCreateStream;
私人最终融资;
@注入
IOXml(IO createStream、F closeStream、XmlSerializer XmlSerializer、选项xmlEncoding){
mXmlSerializer=xmlSerializer;
mXmlEncoding=xmlncoding;
ioCreateStream=createStream;
ioCloseStream=closeStream;
}
/**
*编写一个可XMLWrite的T对象。
*@param osAndSer包含OutputStream和XmlSerializer的元组。
*@param object要写入的对象。
*@return IO monad对象。
*/
受保护的IO写对象(最终T对象){
返回新IO(){
@凌驾
公共单元performIO()引发IOException{
writeXml(mXmlSerializer);
返回单位。单位();
}
};
}
受保护的最终F写对象Fn(最终T对象){
返回新的F(){
@凌驾
公共IO f(a单元){
返回writeObject(object);
}
};
}
/**
*在使用XmlSerializer之前初始化它。
*@param操作一个输出流。
*@param encoding xml文件的编码。
*@返回一个IO操作,但不返回任何内容。
*/
受保护的IO initXml(最终输出流os){
返回新IO(){
@凌驾
公共单元performIO()引发IOException{
setOutput(os,mXmlEncoding.toNull());
mXmlSerializer.startDocument(mxmlencode.toNull(),true);
返回单位。单位();
}
};
}
/**
*完成后关闭XmlSerializer。
*@返回一个IO操作,但不返回任何内容。
*/
受保护的IO closeXml(){
返回新IO(){
@凌驾
公共单元performIO()引发IOException{
mXmlSerializer.endDocument();
返回单位。单位();
}
};
}
受保护的最终F closeXmlFn(){
返回新的F(){
@凌驾
公共IO f(a单元){
返回closeXml();
}
};
}
@凌驾
public void close()引发IOException{
closeXml().performIO();
}
@凌驾
公共无效写入(T对象){
抛出新的UnsupportedOperationException(“您确定吗?IOXml是一个函数类。请改用liftIO返回的函数。”);
}
/**
*Curried函数,用于在给定对象本身和输出流的情况下编写XML对象。
*@返回curried函数。
*/
受保护的F writeFn(){
//返回外部
返回新的F(){
@凌驾
公共F(最终输出流os){
//回归内心
返回新的F(){
@凌驾
公共IO f(T对象){
返回initXml(os.bind(writeObjectFn(object)).bind(closeXmlFn());
}
};
}
};
}
@凌驾
公共IO写入(最终T对象){
返回IOImpl.bracket(ioCreateStream,
ResultSet rs = DbState.reader("conn-url").run(prepareStatement("select * from table").bind(runStatement());
public class IOXml<T extends XmlWritable> implements DataWriter<T>{
private final XmlSerializer mXmlSerializer;
private final Option<String> mXmlEncoding;
private final IO<OutputStream> ioCreateStream;
private final F<OutputStream, IO<Unit>> ioCloseStream;
@Inject
IOXml(IO<OutputStream> createStream, F<OutputStream, IO<Unit>> closeStream, XmlSerializer xmlSerializer, Option<String> xmlEncoding) {
mXmlSerializer = xmlSerializer;
mXmlEncoding = xmlEncoding;
ioCreateStream = createStream;
ioCloseStream = closeStream;
}
/**
* Write a T object which is XmlWritable.
* @param osAndSer The tuple containing OutputStream and XmlSerializer.
* @param object The object to write.
* @return IO monad object.
*/
protected IO<Unit> writeObject(final T object) {
return new IO<Unit>() {
@Override
public Unit performIO() throws IOException {
object.writeXml(mXmlSerializer);
return Unit.unit();
}
};
}
protected final F<Unit, IO<Unit>> writeObjectFn(final T object) {
return new F<Unit, IO<Unit>>() {
@Override
public IO<Unit> f(Unit a) {
return writeObject(object);
}
};
}
/**
* Initialize the XmlSerializer before using it.
* @param os An OutputStream.
* @param encoding The encoding of the xml file.
* @return An IO action returning nothing.
*/
protected IO<Unit> initXml(final OutputStream os) {
return new IO<Unit>() {
@Override
public Unit performIO() throws IOException {
mXmlSerializer.setOutput(os, mXmlEncoding.toNull());
mXmlSerializer.startDocument(mXmlEncoding.toNull(), true);
return Unit.unit();
}
};
}
/**
* Close the XmlSerializer after.
* @return An IO action returning nothing.
*/
protected IO<Unit> closeXml() {
return new IO<Unit>() {
@Override
public Unit performIO() throws IOException {
mXmlSerializer.endDocument();
return Unit.unit();
}
};
}
protected final F<Unit, IO<Unit>> closeXmlFn() {
return new F<Unit, IO<Unit>>() {
@Override
public IO<Unit> f(Unit a) {
return closeXml();
}
};
}
@Override
public void close() throws IOException {
closeXml().performIO();
}
@Override
public void write(T object) {
throw new UnsupportedOperationException("Are you sure? IOXml is a functional class. Use the function returned by liftIO instead.");
}
/**
* Curried function to write XML objects, given the object itself and an OutputStream.
* @return The curried function.
*/
protected F<OutputStream, F<T, IO<Unit>>> writeFn() {
// returning the outer
return new F<OutputStream, F<T, IO<Unit>>>() {
@Override
public F<T, IO<Unit>> f(final OutputStream os) {
// Returning the inner
return new F<T, IO<Unit>>() {
@Override
public IO<Unit> f(T object) {
return initXml(os).bind(writeObjectFn(object)).bind(closeXmlFn());
}
};
}
};
}
@Override
public IO<Unit> writeIO(final T object) {
return IOImpl.bracket(ioCreateStream, // init
ioCloseStream, // close
Function.partialApply2(writeFn(), object)); // body
}
}