如何检测 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
(签名可能是太笼统了,我想不通)。
我有一个小的 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
(签名可能是太笼统了,我想不通)。