首页 文章

如何找到Pipe的结尾

提问于
浏览
4

在下面的代码中我该怎么做

  • 更改 stdoutCharConsumer ,以便在打印输入流中的所有数据后打印换行符

  • 实施 mixinmixin'

没有进入Pipes.Internal?可能吗?我需要像 生产环境 者的 next 函数 .

我使用Pipes 4.1.0

#!/usr/bin/env runhaskell
{-# OPTIONS_GHC -Wall #-}

import Pipes

digits, characters :: Monad m => Producer Char m ()
digits = each "0123456789"
characters = each "abcdefghijklmnopqrstuvwxyz"

interleave :: Monad m => Producer a m () -> Producer a m () -> Producer a m ()
interleave a b = do
  n <- lift $ next a
  case n of
    Left () -> b
    Right (x, a') -> do
      yield x
      interleave b a'

stdoutCharConsumer :: Consumer Char IO ()
stdoutCharConsumer = await >>= liftIO . putChar >> stdoutCharConsumer

-- first element of the mixin should go first
mixin :: Monad m => Producer b m () -> Pipe a b m ()
mixin = undefined

-- first element of the pipe should go first
mixin' :: Monad m => Producer b m () -> Pipe a b m ()
mixin' = undefined

main :: IO ()
main = do

    -- this prints "a0b1c2d3e4f5g6h7i8j9klmnopqrstuvwxyz"
    runEffect $ interleave characters digits >-> stdoutCharConsumer
    putStrLn ""

    -- this prints "0a1b2c3d4e5f6g7h8i9jklmnopqrstuvwxyz"
    runEffect $ interleave digits characters >-> stdoutCharConsumer
    putStrLn ""

    -- should print "0a1b2c3d4e5f6g7h8i9jklmnopqrstuvwxyz"
    runEffect $ characters >-> mixin digits >-> stdoutCharConsumer
    putStrLn ""

    -- should print "a1b2c3d4e5f6g7h8i9jklmnopqrstuvwxyz"
    runEffect $ digits >-> mixin characters >-> stdoutCharConsumer
    putStrLn ""

    -- should print "a1b2c3d4e5f6g7h8i9jklmnopqrstuvwxyz"
    runEffect $ characters >-> mixin' digits >-> stdoutCharConsumer
    putStrLn ""

    -- should print "0a1b2c3d4e5f6g7h8i9jklmnopqrstuvwxyz"
    runEffect $ digits >-> mixin' characters >-> stdoutCharConsumer
    putStrLn ""

UPD: 现在,在我阅读了基于拉/推的流之后,我认为即使使用Pipes.Internal也是不可能的 . 这是真的吗?

1 回答

  • 3

    ConsumersPipes 都不知道上游输入结束 . 你需要 pipes-parse 来自 pipes-parse .

    Consumer 相比, Parser 更直接了解 Producer ;它们的draw函数(大致类似于 await )在找到输入结束时返回 Nothing .

    import qualified Pipes.Parse as P
    
    stdoutCharParser :: P.Parser Char IO ()
    stdoutCharParser = P.draw >>= \ma ->
        case ma of 
            Nothing -> liftIO (putStrLn "\n")
            Just c -> liftIO (putChar c) >> stdoutCharParser
    

    要运行解析器,我们调用 evalStateT 而不是 runEffect

    P.evalStateT stdoutCharParser (interleave characters digits)
    

    至于 mixinmixin' ,我怀疑他们不可能按照预期写作 . 原因是结果 Pipe 必须知道上游终止,以便知道何时产生作为参数传递的 Producer 的剩余值 .

相关问题