Haskell Pipes - 获取管道中最后一个Proxy的返回值 [英] Haskell Pipes - get return value of last Proxy in pipeline
问题描述
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
转换为我们知道不会返回的< 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 return
ing 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 request
ed 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屋!