【问题标题】:How to detect last chunk in a Haskell Pipe?如何检测 Haskell Pipe 中的最后一个块?
【发布时间】:2015-12-13 22:27:42
【问题描述】:

我有一个小型 Haskell Pipe 可以打印出它运行了多少次:

counterPipe :: Pipe String String IO r
counterPipe = go 0
  where
    go n = do
      await >>= yield
      let n' = succ n
      liftIO $ putStrLn $ "Chunk " ++ show n'
      go n'

我希望能够在处理完最后一个块后打印出一条消息,并可能执行其他任务。我该怎么做?

【问题讨论】:

    标签: haskell haskell-pipes


    【解决方案1】:

    我可以通过将counterPipe 的输入类型更改为Maybe String 并在上游管道完成后注入额外的Nothing 来实现此功能:

    import Pipes
    import Pipes.Core (respond)
    import Control.Applicative ((<*))
    
    withEOF :: (Monad m) => Proxy a' a b' b m r -> Proxy a' a b' (Maybe b) m r
    withEOF p = for p (respond . Just) <* respond Nothing
    
    counterPipe :: Pipe (Maybe String) String IO Int
    counterPipe = go 0
      where
        go n = do
            mx <- await
    
            case mx of
                Just x -> do
                    yield x
                    let n' = succ n
                    liftIO $ putStrLn $ "Chunk " ++ show n'
                    go n'
                Nothing -> do
                    return n
    
    finishCounter :: Int -> Pipe a b IO ()
    finishCounter n = liftIO $ putStrLn $ unwords ["Finished after", show n, "chunks"]
    

    示例驱动程序:

    import qualified Pipes.Prelude as P
    main = runEffect $ withEOF P.stdinLn >-> (counterPipe >>= finishCounter) >-> P.stdoutLn
    

    我认为这种模式应该可以抽象成类似的东西

    whileJust :: (Monad m) => Proxy a' a b' b m r -> Proxy a' (Maybe a) b' b m (Maybe r)
    

    所以你可以写

    withEOF P.stdinLn >-> (whileJust counterPipe >>= maybe (return ()) finishCounter) >-> P.stdoutLn
    

    无需更改您原来的counterPipe 定义; 但是我以前从未使用过Pipes(上面的解决方案是通过查看类型和玩type-domino来解决的)所以我没有设法写whileJust(签名可能在某些方面过于通用我无法弄清楚)。

    【讨论】:

      猜你喜欢
      • 1970-01-01
      • 2016-09-25
      • 2011-03-30
      • 1970-01-01
      • 1970-01-01
      • 1970-01-01
      • 1970-01-01
      • 1970-01-01
      • 1970-01-01
      相关资源
      最近更新 更多