【问题标题】:Haskell Pipes - get return value of last Proxy in pipelineHaskell Pipes - 获取管道中最后一个代理的返回值
【发布时间】:2015-06-01 08:08:42
【问题描述】:

假设我在 Haskell Pipes 中有两个 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 的返回值的惯用管道方式是什么,即使它没有首先终止?

到目前为止,我认为如果不执行某种 icky 带内信令,这是不可能的,因此consume 知道流已完成。最后一个代理知道关闭的唯一方法是从await 获取一些东西,所以我可以向它发送一个空的ByteString 来表示流已完成。只是感觉不对劲。我现在拥有的是一个单独的 MVar,它可以提供退出值,但我认为必须有一种更惯用的方式来做到这一点。

【问题讨论】:

    标签: haskell haskell-pipes


    【解决方案1】:

    如果没有带内信号,Consumer 永远不可能有“返回值”,如果 Producer 先返回。如果生产者是returning,则意味着必须阻止Consumer 等待请求的值。 Consumer 将永远不会再次运行,因此永远不会有机会 return,直到 Consumer 获得具有请求值的带内信号。

    仅仅因为信号是带内的并不意味着它需要“恶心”。我们可以通过捕获return 并将其转发到下游,将可能返回的Producer 转换为我们知道不会返回的Producer(它的返回类型为forall r' . r')。我们这样做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 结束时,您需要明确处理当值为requested 时要执行的操作,而不是获取响应(在Right 中),而是获取上游生产者的返回值(在Left)。

    【讨论】:

      【解决方案2】:

      谢谢。我想出的是类似的东西

      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)。 (如果下游先终止,那么上游进程就没有任何关系了,只是终止它,所以提供退出代码没有任何意义。)

      【讨论】:

        猜你喜欢
        • 1970-01-01
        • 1970-01-01
        • 1970-01-01
        • 1970-01-01
        • 1970-01-01
        • 1970-01-01
        • 1970-01-01
        • 1970-01-01
        • 1970-01-01
        相关资源
        最近更新 更多