haskell - 如何找到管道的末端

标签 haskell haskell-pipes

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

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

  • 实现mixinmixin'

不进入 Pipes.Internal?是否可以?我需要像生产者的 next 函数这样的东西。

我使用管道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 也是不可能的。这是真的吗?

最佳答案

消费者管道都不知道上游输入结束。为此,您需要来自 pipes-parseParser

Consumer相比,ParserProducer有更直接的了解;他们的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 的剩余值。

关于haskell - 如何找到管道的末端,我们在Stack Overflow上找到一个类似的问题: https://stackoverflow.com/questions/22425432/

相关文章:

Haskell:原子 IO 包装器/惰性?

haskell - 在 Haskell 中折叠生产者/解析器时的空间爆炸

haskell - 尝试安装 cabal 包 sdl-mpeg 找不到包含文件 smpeg.h

haskell - 具有下游状态且无损失的惯用双向管道

haskell - 如何将状态与管道一起使用?

haskell - 将 StateT IO monad 转换为使用 Control.Proxy - 哪个是服务器,哪个是客户端?

haskell - 根据时间限制管道?

haskell - Haskell 示例中的函数组合

string - Haskell 读取文件 : Couldn't match expected type ‘[String]’ with actual type ‘IO String’

haskell - Haskell 有没有一种方法可以检查一个模块是否导出与另一个模块相同的函数?