Java 8 中具有链接的单子函数组合
Monadic Function composition with chaining in Java 8
当值通过每个函数通过管道传输时,我应该能够以某种方式指定这样的链。
a::create -> a::processing -> a::updating -> a:uploading
在后续文章的上下文中,我想将方法与一个方法链接起来,在修改结果时将结果传递给下一个方法。
https://dzone.com/articles/higher-order-functions
https://dzone.com/articles/functional-programming-java-8
我的演示将尝试展示我想要的最终结果。它将是单个 parameter/argument 管道传输到每个方法(如 monad)并且应该更容易在链中指定任意数量的方法。
我一直在用其他语言做这件事,所以我想弄明白如何在 java 中做。
所有方法都将接收相同类型的参数,而且只有一个。
Class 值
public class Value {
public String progress = "";
}
Class条
public class Article {
public void create(Value value) {
value.progress += "creating ";
}
public void processing(Value value) {
value.progress += "processing ";
}
public void updating(Value value) {
value.progress += "updating ";
}
public void uploading(Value value) {
value.progress += "uploading ";
}
}
主要Class
public class Main {
public static void main(String[] args) {
Value v = new Value();
Article a = new Article();
a.create(v);
a.processing(v);
a.updating(v);
a.uploading(v);
}
}
鉴于不可变状态在函数式编程中更可取,我调整了 Value
- 这具有使进度函数更清晰的额外好处。
public class Value {
public final String progress;
public Value() {
this("");
}
public Value(final String progress) {
this.progress = progress;
}
}
代替方法,Article
有函数。可以使用 andThen
.
链接这些函数
import java.util.function.Function;
public class Article {
private final Function<Value, Value> create = v -> new Value(v.progress + "creating ");
private final Function<Value, Value> processing = v -> new Value(v.progress + "processing ");
private final Function<Value, Value> updating = v -> new Value(v.progress + "updating ");
private final Function<Value, Value> uploading = v -> new Value(v.progress + "uploading ");
public static void main(String[] args) {
final Article a = new Article();
final Value v = a.create.andThen(a.processing).andThen(a.updating).andThen(a.uploading).apply(new Value());
System.out.println(v.progress);
}
}
System.out.println
的结果就是creating processing updating uploading
。
更新
根据您对在方法中创建函数的偏好,您只需更改 Article
实现,使其具有类似的功能。请注意,我正在使用 Value
.
的原始(可变)实现
public class Article {
public Function<Value, Value> create() {
return v -> {
v.progress += "creating ";
return v;
};
}
public Function<Value, Value> processing() {
return v -> {
v.progress += "processing ";
return v;
};
}
public Function<Value, Value> updating() {
return v -> {
v.progress += "updating ";
return v;
};
}
public Function<Value, Value> uploading() {
return v -> {
v.progress += "uploading ";
return v;
};
}
public static void main(String[] args) {
final Article a = new Article();
final Value v = a.create()
.andThen(a.processing())
.andThen(a.updating())
.andThen(a.uploading())
.apply(new Value());
System.out.println(v.progress);
}
}
更新 2
已请求静态方法引用,现在开始吧。我要添加一个附带条件,如果有人向我提供此代码,我会想要一个非常好的设计选择理由。
public class Article {
public static Value create(Value v) {
v.progress += "creating ";
return v;
}
public static Value processing(Value v) {
v.progress += "processing ";
return v;
}
public static Value updating(Value v) {
v.progress += "updating ";
return v;
}
public static Value uploading(Value v) {
v.progress += "uploading ";
return v;
}
public static void main(String[] args) {
Optional<Value> maybeValue = Stream.of(new Value())
.map(Article::create)
.map(Article::processing)
.map(Article::updating)
.map(Article::uploading)
.findFirst();
maybeValue.ifPresent(v -> System.out.println(v.progress));
}
}
这是与 Java8 流链接的一种方法。
public static class Article {
public Stream<Value> create(Value value) {
value.progress += "creating ";
return Stream.of(value);
}
public Stream<Value> processing(Value value) {
value.progress += "processing ";
return Stream.of(value);
}
public Stream<Value> updating(Value value) {
value.progress += "updating ";
return Stream.of(value);
}
public Stream<Value> uploading(Value value) {
value.progress += "uploading ";
return Stream.of(value);
}
public Stream<Value> error(Value value) {
return Stream.empty();
}
}
public static void main(String[] args) {
Article a = new Article();
Stream.of(new Value())
.flatMap(a::create)
.flatMap(a::processing)
.flatMap(a::updating)
.flatMap(a::uploading)
.forEach(v -> System.out.println(v.progress));
Stream.of(new Value())
.flatMap(a::create)
.flatMap(a::processing)
.flatMap(a::updating)
.flatMap(a::error)
.forEach(v -> System.out.println(v.progress));
}
输出:
creating processing updating uploading
在不将 Article 方法修改为 return Stream
的情况下执行此操作
public static class Article {
public Value create(Value value) {
value.progress += "creating ";
return value;
}
public Value processing(Value value) {
value.progress += "processing ";
return value;
}
public Value updating(Value value) {
value.progress += "updating ";
return value;
}
public Value uploading(Value value) {
value.progress += "uploading ";
return value;
}
}
@FunctionalInterface
public interface ThrowingFunction<T, R> {
R apply(T v) throws Exception;
}
public static Function<Value, Stream<Value>> wrap(ThrowingFunction<Value, Value> call) {
return (Value v) -> {
try {
return Stream.of(call.apply(v));
} catch (Exception e) {
return Stream.empty();
}
};
}
public static void main(String[] args) {
Article a = new Article();
Stream.of(new Value())
.flatMap(wrap(a::create))
.flatMap(wrap(a::processing))
.flatMap(wrap(a::updating))
.flatMap(wrap(a::uploading))
.forEach(v -> System.out.println(v.progress));
}
这不是答案,也没有用,而是我根据给定的答案起草的,以接近我想要的东西。请 post 您的 edits/answer 基于此。
价值
public class Value {
public String progress = "";
}
文章 - 您可以根据需要修改方法的签名。
public class Article {
public Value create(Value value) {
value.progress += "creating ";
return value;
}
public Value processing(Value value) {
value.progress += "processing ";
return value;
}
public Value updating(Value value) {
value.progress = "updating ";
return value;
}
public Value uploading(Value value) {
value.progress += "uploading ";
return value;
}
}
主要(我应该可以做这样的事情)
public class Main {
public static void main(String[] args) {
Article a = new Article();
final Value v = a.create
.andThen(a.processing) // or a::processing
.andThen(a.updating) // or a::updating
.andThen(a.uploading)
.apply(new Value());
System.out.println(v.progress);
}
}
当值通过每个函数通过管道传输时,我应该能够以某种方式指定这样的链。
a::create -> a::processing -> a::updating -> a:uploading
在后续文章的上下文中,我想将方法与一个方法链接起来,在修改结果时将结果传递给下一个方法。
https://dzone.com/articles/higher-order-functions
https://dzone.com/articles/functional-programming-java-8
我的演示将尝试展示我想要的最终结果。它将是单个 parameter/argument 管道传输到每个方法(如 monad)并且应该更容易在链中指定任意数量的方法。
我一直在用其他语言做这件事,所以我想弄明白如何在 java 中做。
所有方法都将接收相同类型的参数,而且只有一个。
Class 值
public class Value {
public String progress = "";
}
Class条
public class Article {
public void create(Value value) {
value.progress += "creating ";
}
public void processing(Value value) {
value.progress += "processing ";
}
public void updating(Value value) {
value.progress += "updating ";
}
public void uploading(Value value) {
value.progress += "uploading ";
}
}
主要Class
public class Main {
public static void main(String[] args) {
Value v = new Value();
Article a = new Article();
a.create(v);
a.processing(v);
a.updating(v);
a.uploading(v);
}
}
鉴于不可变状态在函数式编程中更可取,我调整了 Value
- 这具有使进度函数更清晰的额外好处。
public class Value {
public final String progress;
public Value() {
this("");
}
public Value(final String progress) {
this.progress = progress;
}
}
代替方法,Article
有函数。可以使用 andThen
.
import java.util.function.Function;
public class Article {
private final Function<Value, Value> create = v -> new Value(v.progress + "creating ");
private final Function<Value, Value> processing = v -> new Value(v.progress + "processing ");
private final Function<Value, Value> updating = v -> new Value(v.progress + "updating ");
private final Function<Value, Value> uploading = v -> new Value(v.progress + "uploading ");
public static void main(String[] args) {
final Article a = new Article();
final Value v = a.create.andThen(a.processing).andThen(a.updating).andThen(a.uploading).apply(new Value());
System.out.println(v.progress);
}
}
System.out.println
的结果就是creating processing updating uploading
。
更新
根据您对在方法中创建函数的偏好,您只需更改 Article
实现,使其具有类似的功能。请注意,我正在使用 Value
.
public class Article {
public Function<Value, Value> create() {
return v -> {
v.progress += "creating ";
return v;
};
}
public Function<Value, Value> processing() {
return v -> {
v.progress += "processing ";
return v;
};
}
public Function<Value, Value> updating() {
return v -> {
v.progress += "updating ";
return v;
};
}
public Function<Value, Value> uploading() {
return v -> {
v.progress += "uploading ";
return v;
};
}
public static void main(String[] args) {
final Article a = new Article();
final Value v = a.create()
.andThen(a.processing())
.andThen(a.updating())
.andThen(a.uploading())
.apply(new Value());
System.out.println(v.progress);
}
}
更新 2
已请求静态方法引用,现在开始吧。我要添加一个附带条件,如果有人向我提供此代码,我会想要一个非常好的设计选择理由。
public class Article {
public static Value create(Value v) {
v.progress += "creating ";
return v;
}
public static Value processing(Value v) {
v.progress += "processing ";
return v;
}
public static Value updating(Value v) {
v.progress += "updating ";
return v;
}
public static Value uploading(Value v) {
v.progress += "uploading ";
return v;
}
public static void main(String[] args) {
Optional<Value> maybeValue = Stream.of(new Value())
.map(Article::create)
.map(Article::processing)
.map(Article::updating)
.map(Article::uploading)
.findFirst();
maybeValue.ifPresent(v -> System.out.println(v.progress));
}
}
这是与 Java8 流链接的一种方法。
public static class Article {
public Stream<Value> create(Value value) {
value.progress += "creating ";
return Stream.of(value);
}
public Stream<Value> processing(Value value) {
value.progress += "processing ";
return Stream.of(value);
}
public Stream<Value> updating(Value value) {
value.progress += "updating ";
return Stream.of(value);
}
public Stream<Value> uploading(Value value) {
value.progress += "uploading ";
return Stream.of(value);
}
public Stream<Value> error(Value value) {
return Stream.empty();
}
}
public static void main(String[] args) {
Article a = new Article();
Stream.of(new Value())
.flatMap(a::create)
.flatMap(a::processing)
.flatMap(a::updating)
.flatMap(a::uploading)
.forEach(v -> System.out.println(v.progress));
Stream.of(new Value())
.flatMap(a::create)
.flatMap(a::processing)
.flatMap(a::updating)
.flatMap(a::error)
.forEach(v -> System.out.println(v.progress));
}
输出:
creating processing updating uploading
在不将 Article 方法修改为 return Stream
的情况下执行此操作public static class Article {
public Value create(Value value) {
value.progress += "creating ";
return value;
}
public Value processing(Value value) {
value.progress += "processing ";
return value;
}
public Value updating(Value value) {
value.progress += "updating ";
return value;
}
public Value uploading(Value value) {
value.progress += "uploading ";
return value;
}
}
@FunctionalInterface
public interface ThrowingFunction<T, R> {
R apply(T v) throws Exception;
}
public static Function<Value, Stream<Value>> wrap(ThrowingFunction<Value, Value> call) {
return (Value v) -> {
try {
return Stream.of(call.apply(v));
} catch (Exception e) {
return Stream.empty();
}
};
}
public static void main(String[] args) {
Article a = new Article();
Stream.of(new Value())
.flatMap(wrap(a::create))
.flatMap(wrap(a::processing))
.flatMap(wrap(a::updating))
.flatMap(wrap(a::uploading))
.forEach(v -> System.out.println(v.progress));
}
这不是答案,也没有用,而是我根据给定的答案起草的,以接近我想要的东西。请 post 您的 edits/answer 基于此。
价值
public class Value {
public String progress = "";
}
文章 - 您可以根据需要修改方法的签名。
public class Article {
public Value create(Value value) {
value.progress += "creating ";
return value;
}
public Value processing(Value value) {
value.progress += "processing ";
return value;
}
public Value updating(Value value) {
value.progress = "updating ";
return value;
}
public Value uploading(Value value) {
value.progress += "uploading ";
return value;
}
}
主要(我应该可以做这样的事情)
public class Main {
public static void main(String[] args) {
Article a = new Article();
final Value v = a.create
.andThen(a.processing) // or a::processing
.andThen(a.updating) // or a::updating
.andThen(a.uploading)
.apply(new Value());
System.out.println(v.progress);
}
}