Mar*_*szS 2 java java-stream vavr
是否有最简单的方法可以在下面编写此代码而不使用toStream()?
import io.vavr.collection.List;
import io.vavr.control.Option;
import lombok.Value;
public class VavrDemo {
public static void main(String[] args) {
Foo bar = new Foo(List.of(new Bar(1), new Bar(2)));
Number value = Option.some(bar)
.toStream() // <- WTF?!?
.flatMap(Foo::getBars)
.map(Bar::getValue)
.sum();
System.out.println(value);
}
@Value
static class Foo {
private List<Bar> bars;
}
@Value
static class Bar {
private int value;
}
}
Run Code Online (Sandbox Code Playgroud)
Dan*_*ich 12
选项是所谓的Monad.这只是告诉我们flatMap函数遵循特定的规律,即
让
然后,Monad接口的所有实例都应遵守Functor定律(这里省略)和三个控制定律:
unit(a).flatMap(f) ? f am.flatMap(unit) ? mm.flatMap(f).flatMap(g) ? m.flatMap(x -> f.apply(x).flatMap(g))目前Vavr已经(简化):
interface Option<T> {
<U> Option<U> flatMap(Function<T, Option<U>> mapper) {
return isEmpty() ? none() : mapper.apply(get());
}
}
Run Code Online (Sandbox Code Playgroud)
此版本遵守Monad法律.
无法按照您希望的方式定义Option.flatMap仍然遵守Monad法则.例如,想象一个flatMap版本,它接受一个带有Iterable的函数作为结果.所有Vavr集合都有这样的flatMap方法,但对于Option,它没有意义:
interface Option<T> {
<U> Option<U> flatMap(Function<T, Iterable<U>> mapper) {
if (isEmpty()) {
return none();
} else {
Iterable<U> iterable = mapper.apply(get());
if (isEmpty(iterable)) {
return none();
} else {
U resultValue = whatToDoWith(iterable); // ???
return some(resultValue);
}
}
}
}
Run Code Online (Sandbox Code Playgroud)
你看?我们可以做的最好的事情是只获取iterable中的一个元素,以防它不为空.除了它没有使用你可能期望的结果(在上面的VavrTest中),我们可以证明这个'幻想'版本的flatMap确实打破了Monad法则.
如果你遇到这种情况,请考虑稍微改变你的电话.例如,VavrTest可以表示如下:
Number value = Option.some(bar)
.map(b -> b.getBars().map(Bar::getValue).sum())
.getOrElse(0);
Run Code Online (Sandbox Code Playgroud)
我希望这有帮助,上面的Monad部分并没有完全吓跑你.实际上,开发人员不需要了解Monads的任何信息就可以利用Vavr.
免责声明:我是Vavr的创始人(原名:Javaslang)
| 归档时间: |
|
| 查看次数: |
1212 次 |
| 最近记录: |