具有CompletableFuture

时间:2017-02-13 13:47:13

标签: java haskell java-8 completable-future

我正在尝试避免在将2个独立的组合与返回第三个的CompletableFuture组合时嵌套BiFunction。 目前,使用thenCombine()不会削减它:

// What I have
public CompletableFuture<CompletableFuture<C>> doStuff() {
    CompletableFuture<A> aFuture = makeSomeA();
    CompletableFuture<B> bFuture = makeSomeB();
    CompletableFuture<CompletableFuture<C>> cFuture = aFuture.thenCombine(bFuture, this::makeSomeC);
    return cFuture;
}

// What I want
public CompletableFuture<C> doStuff() {
    CompletableFuture<A> aFuture = makeSomeA();
    CompletableFuture<B> bFuture = makeSomeB();
    // obv this method does not exist
    CompletableFuture<C> c = aFuture.thenBicompose(bFuture, this::makeSomeC);
} 

private CompletableFuture<A> makeSomeA() {...}
private CompletableFuture<B> makeSomeB() {...}
private CompletableFuture<C> makeSomeC(A a, B b) {...}

如果有一个CompletableFuture monad,我基本上试图找到一种看起来像haskell的方式:

doStuff :: CompletableFuture C
doStuff = do
    a <- makeSomeA
    b <- makeSomeB
    makeSomeC a b

makeSomeA :: CompletableFuture A
makeSomeB :: CompletableFuture B
makeSomeC :: A -> B -> CompletableFuture C

我在某处读到join()是可完成未来的flatMap,所以我想我可以使用这种方法做aFuture.thenCombine(bFuture, ((Function<CompletableFuture<C>,C>) CompletableFuture::join).compose(this::makeSomeC)这样的事情,但我不确定这是不是正确的/建议的方式去。而且我不能说这有助于以任何方式提供可读性......

2 个答案:

答案 0 :(得分:7)

对我而言,thenCompose似乎是Haskell Monad.bind的直接等价物。

thenCompose可以与Haskell monad绑定相同的方式嵌套,这也是Haskell中do-expression的结果。使用它可以解决您的问题:

public CompletableFuture<C> doStuff() {
    CompletableFuture<A> aFuture = makeSomeA();
    CompletableFuture<B> bFuture = makeSomeB();
    return aFuture.thenCompose(a -> bFuture.thenCompose(b -> makeSomeC(a, b)));
}

类型说明

通过检查函数的类型可以看出这一点。

Monad绑定 - 在Haskell中写入>>= - 具有以下类型:

(>>=) :: Monad m => m a -> (a -> m b) -> m b
Java中的

thenCompose具有以下签名:

public <U> CompletionStage<U> thenCompose(Function<? super T, ? extends CompletionStage<U>> fn)

以上转换为Haskell语法,附加参数为显式this,如下所示:

thenCompose :: CompletionStage T -> (T -> CompletionStage U) -> CompletionStage U  

我们可以看到它具有与Haskell类型相同的结构。区别在于名称,而且Haskell对更高级别的支持的事实并不完全由Java接口表达。

关于问题

中的Haskell代码的注释

但我对你的Haskell代码感到有些困惑。对我来说,看起来你的Haskell代码正在执行以下操作:

public CompletableFuture<C> doStuff() {
    return makeSomeA().thenCompose(a -> makeSomeB().thenCompose(b -> makeSomeC(a, b)));
}

也就是说,等到makeSomeA操作完成后再开始makeSomeB。另一方面,Java代码并行启动两个操作,然后在C开始之前等待结果。但也许这是一个懒惰的事情。

答案 1 :(得分:6)

我想最简单的解决方案就是之后应用Exception : System.NullReferenceException: Object reference not set to an instance of an object. at Microsoft.ConfigurationManagement.PowerShell.Prov ider.CMDriveProvider.NewItem(String path, String itemTypeName, Object newItemValue) at System.Management.Automation.SessionStateInternal .NewItemPrivate(CmdletProvider providerInstance, String path, String type, Object content, CmdletProviderContext context) TargetObject : CategoryInfo : NotSpecified: (:) [New-Item], NullReferenceException FullyQualifiedErrorId : System.NullReferenceException,Microsoft.PowerShell.Comm ands.NewItemCommand ErrorDetails : InvocationInfo : System.Management.Automation.InvocationInfo ScriptStackTrace : at set-drvsource, C:\temp\quick import_cli-1.1\quickimport_cli-1.1\Invoke-QuickImport.p s1: line 51 at main, C:\temp\quickimport_cl i-1.1\quickimport_cli-1.1\Invoke-QuickImport.ps1: line 101 at <ScriptBlock>, C:\temp\quick import_cli-1.1\quickimport_cli-1.1\Invoke-QuickImport.p s1: line 165 PipelineIterationInfo : {} PSMessageDetails :

thenCompose(identity())

或者,引入一个简单的public CompletableFuture<C> doStuff() { CompletableFuture<A> aFuture = makeSomeA(); CompletableFuture<B> bFuture = makeSomeB(); CompletableFuture<CompletableFuture<C>> cFuture = aFuture.thenCombine(bFuture, this::makeSomeC); return cFuture.thenCompose(Function.identity()); } 类来组合A和B的结果并使用Pair

thenCompose()

没有public CompletableFuture<C> doStuff() { CompletableFuture<A> aFuture = makeSomeA(); CompletableFuture<B> bFuture = makeSomeB(); CompletableFuture<Pair<A, B>> cFuture = aFuture.thenCombine(bFuture, Pair::new); return cFuture.thenCompose(p -> makeSomeC(p.a, p.b)); } private static class Pair<A, B> { A a; B b; public Pair(A a, B b) { this.a = a; this.b = b; } } 的第三种选择:

Pair