Haskell 管道 - 获取管道中最后一个代理的 return 值
Haskell Pipes - get return value of last Proxy in pipeline
假设我在 Haskell 管道中有两个 Proxy
。它们代表外部系统进程。
produce :: MonadIO m => Producer ByteString m ExitCode
consume :: MonadIO m => Consumer ByteString m ExitCode
所以我将它们连接到一个 Effect
中,像这样:
effect :: Effect m ExitCode
effect = produce >-> consume
这个 Effect
将给我第一个 Proxy
终止的 ExitCode
。通常这将是 produce
,而不是 consume
。即使它没有先终止,获取 consume
的 return 值的惯用 Pipes 方法是什么?
到目前为止,我认为如果不进行某种令人讨厌的带内信号发送是不可能的,因此 consume
知道流已完成。最后一个代理知道关闭的唯一方法是从 await
中获取一些东西,这样我就可以向它发送一个空的 ByteString
来表示流已完成。只是感觉不对。我现在得到的是一个单独的 MVar,它可以提供退出值,但我认为必须有一种更惯用的方法来做到这一点。
没有带内信号,如果 Producer
return 首先出现,Consumer
将永远不可能有 "return value"。如果生产者 return
ing 意味着 Consumer
必须被阻塞等待请求的值。 Consumer
将永远不会再 运行,因此永远不会有机会 return
,直到 Consumer
获得具有请求值的带内信号。
仅仅因为信号是带内的并不意味着它需要是 "icky"。我们可以将可能 return 的 Producer
转换为我们知道不 return 的 Producer
(它的 return 类型是 forall r' . r'
)捕获 return
并将其转发到下游。我们这样做 forever
以防另一个请求返回上游。
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 <\)
在 Consumer
结束时,您需要明确处理值被 request
ed 时要做什么,而不是得到响应(在 Right
中),您得到 return 上游生产者的值(在 Left
中)。
谢谢。我想出的是
produce :: MonadIO m => Producer (Either ExitCode ByteString) m r
consume :: MonadIO m => Consumer (Either ExitCode ByteString) m (Maybe ExitCode, ExitCode)
因此,当 Effect 运行时,如果下游进程终止,我将得到一个 (Nothing, code),或者如果上游进程首先终止,我将得到一个 (Just code1, code2)。 (如果下游先终止,那么上游进程除了终止它就没有其他事情可做了,所以提供退出代码没有任何意义。)
假设我在 Haskell 管道中有两个 Proxy
。它们代表外部系统进程。
produce :: MonadIO m => Producer ByteString m ExitCode
consume :: MonadIO m => Consumer ByteString m ExitCode
所以我将它们连接到一个 Effect
中,像这样:
effect :: Effect m ExitCode
effect = produce >-> consume
这个 Effect
将给我第一个 Proxy
终止的 ExitCode
。通常这将是 produce
,而不是 consume
。即使它没有先终止,获取 consume
的 return 值的惯用 Pipes 方法是什么?
到目前为止,我认为如果不进行某种令人讨厌的带内信号发送是不可能的,因此 consume
知道流已完成。最后一个代理知道关闭的唯一方法是从 await
中获取一些东西,这样我就可以向它发送一个空的 ByteString
来表示流已完成。只是感觉不对。我现在得到的是一个单独的 MVar,它可以提供退出值,但我认为必须有一种更惯用的方法来做到这一点。
没有带内信号,如果 Producer
return 首先出现,Consumer
将永远不可能有 "return value"。如果生产者 return
ing 意味着 Consumer
必须被阻塞等待请求的值。 Consumer
将永远不会再 运行,因此永远不会有机会 return
,直到 Consumer
获得具有请求值的带内信号。
仅仅因为信号是带内的并不意味着它需要是 "icky"。我们可以将可能 return 的 Producer
转换为我们知道不 return 的 Producer
(它的 return 类型是 forall r' . r'
)捕获 return
并将其转发到下游。我们这样做 forever
以防另一个请求返回上游。
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 <\)
在 Consumer
结束时,您需要明确处理值被 request
ed 时要做什么,而不是得到响应(在 Right
中),您得到 return 上游生产者的值(在 Left
中)。
谢谢。我想出的是
produce :: MonadIO m => Producer (Either ExitCode ByteString) m r
consume :: MonadIO m => Consumer (Either ExitCode ByteString) m (Maybe ExitCode, ExitCode)
因此,当 Effect 运行时,如果下游进程终止,我将得到一个 (Nothing, code),或者如果上游进程首先终止,我将得到一个 (Just code1, code2)。 (如果下游先终止,那么上游进程除了终止它就没有其他事情可做了,所以提供退出代码没有任何意义。)