Haskell Pipes - 获取管道中最后一个Proxy的返回值 [英] Haskell Pipes - get return value of last Proxy in pipeline

查看:97
本文介绍了Haskell Pipes - 获取管道中最后一个Proxy的返回值的处理方法,对大家解决问题具有一定的参考价值,需要的朋友们下面随着小编来一起学习吧!

问题描述

假设我在Haskell Pipes中有两个 Proxy 。它们代表了外部系统进程。

  produce :: MonadIO m => Producer ByteString m ExitCode 
consume :: MonadIO m =>消费者ByteString m ExitCode

所以我把它们挂到效果,如下所示:

  effect:Effect m ExitCode 
effect = produce> - >消费

这个效果会给我来自终止的第一个代理 ExitCode 。通常这将是产生,而不是消费。什么是惯用的Pipes方式来获取消费的返回值,即使它不是先终止?



我认为如果不做某种恶心的带内信号传递,这是不可能的,因此消耗知道流已完成。最后一个代理知道关闭的唯一方法是从 await 中获取某些内容,这样我就可以发送一个空的 ByteString 表示流已完成。但这只是感觉不对。我现在得到的是一个单独的MVar,可以提供退出价值,但我认为必须有一个更习惯的方式来做到这一点。

解决方案

如果 Producer没有带内信号,那么 Consumer 将不可能具有返回值首先返回。如果生产者 return ing,那意味着 Consumer 必须被阻止等待请求的值。 Consumer 永远不会再运行,因此从来没有机会 return ,直到消费者获得带有请求值的带内信号。



仅仅因为信号带内并不意味着它需要恶心。我们可以将可能返回的 Producer 转换为我们知道不会返回的< Producer >(它的返回类型是<通过捕获 return 并将其向下游转发,从而获得一个或多个c code> forall r'。r')。我们这样做 <$ c $

  returnDownstream :: Monad  在另一个请求返回上游的情况下。 m =>代理a'a b'b m r  - >代理a'a b'(或者r b)m r'
returnDownstream =(forever .response.Left =<<)。 (响应。权利< \\)

消费者 end你需要明确地处理当值 request ed时要做什么,而不是得到响应(在)你得到上游生产者的返回值(在 Left 中)。


Let's say I have two Proxy in Haskell Pipes. They represent external system processes.

produce :: MonadIO m => Producer ByteString m ExitCode
consume :: MonadIO m => Consumer ByteString m ExitCode

So I hook them into an Effect, like this:

effect :: Effect m ExitCode
effect = produce >-> consume

This Effect is going to give me the ExitCode from the first Proxy that terminates. Ordinarily this will be the produce, not the consume. What's the idiomatic Pipes way to get the return value of the consume even if it does not terminate first?

So far I am thinking this is not possible without doing some sort of icky in-band signaling so the consume knows the stream is done. The only way the last Proxy knows to shut down is by getting something from an await, so I could send it an empty ByteString to signal that the stream is done. That just doesn't feel right though. What I've got now is a separate MVar that can provide the exit value but I'm thinking there has to be a more idiomatic way to do this.

解决方案

Without in-band signaling it will never be possible for the Consumer to have a "return value" if the Producer returns first. If the producer is returning that means the Consumer must be blocked waiting for a requested value. The Consumer will never run again, and thus never have an opportunity to return, until the Consumer gets an in-band signal with the requested value.

Just because signaling is in-band doesn't mean it needs to be "icky". We can convert a Producer that might return into a Producer that we know doesn't return (it's return type is forall r' . r') by capturing the return and forwarding it downstream. We do this forever in case another request comes back upstream.

returnDownstream :: Monad m => Proxy a' a b' b m r -> Proxy a' a b' (Either r b) m r'
returnDownstream = (forever . respond . Left =<<) . (respond . Right <\\)

At the Consumer end you need to explicitly handle what to do when a value is requested but instead of getting the response (in a Right) you get the return value of the upstream producer (in a Left).

这篇关于Haskell Pipes - 获取管道中最后一个Proxy的返回值的文章就介绍到这了,希望我们推荐的答案对大家有所帮助,也希望大家多多支持IT屋!

查看全文
登录 关闭
扫码关注1秒登录
发送“验证码”获取 | 15天全站免登陆