簡體   English   中英

如何檢測Haskell管道中的最后一塊?

[英]How to detect last chunk in a Haskell Pipe?

我有一個小的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'

一旦處理完最后一塊,我希望能夠打印出一條消息,並可能執行其他任務。 我該怎么做呢?

我可以通過將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內編寫(簽名可能太通用了,以至於我無法弄清楚出來)。

暫無
暫無

聲明:本站的技術帖子網頁,遵循CC BY-SA 4.0協議,如果您需要轉載,請注明本站網址或者原文地址。任何問題請咨詢:yoyou2525@163.com.

 
粵ICP備18138465號  © 2020-2024 STACKOOM.COM